Code drop from //branches/cupcake/...@124589
diff --git a/apps/Development/AndroidManifest.xml b/apps/Development/AndroidManifest.xml
index dd31b85..9c6b92b 100644
--- a/apps/Development/AndroidManifest.xml
+++ b/apps/Development/AndroidManifest.xml
@@ -20,7 +20,6 @@
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.DUMP" />
<uses-permission android:name="android.permission.SET_PREFERRED_APPLICATIONS" />
- <uses-permission android:name="android.permission.DELETE_PACKAGES" />
<uses-permission android:name="android.permission.RESTART_PACKAGES" />
<uses-permission android:name="android.permission.SET_ANIMATION_SCALE" />
<uses-permission android:name="android.permission.SET_PROCESS_LIMIT" />
@@ -30,6 +29,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH" />
<uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.ALL_SERVICES" />
+ <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.YouTubeUser" />
<uses-permission android:name="com.google.android.googleapps.permission.ACCESS_GOOGLE_PASSWORD" />
<application android:label="Dev Tools"
@@ -71,6 +71,14 @@
<activity android:name="AppPicker"
android:theme="@android:style/Theme.Dialog">
</activity>
+ <activity android:name="PointerLocation" android:label="Pointer Location"
+ android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
+ android:configChanges="keyboard|keyboardHidden|navigation|orientation">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.TEST" />
+ </intent-filter>
+ </activity>
<activity android:name="DataList">
</activity>
@@ -103,5 +111,30 @@
<category android:name="android.intent.category.TEST" />
</intent-filter>
</activity>
+
+ <activity android:name="RunningProcesses" android:label="Running processes">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.TEST" />
+ </intent-filter>
+ </activity>
+ <activity android:name="ProcessInfo" android:label="Process Information">
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ <activity android:name="AppHwConfigList" android:label="Applications Hw Configuration">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.TEST" />
+ </intent-filter>
+ </activity>
+ <activity android:name="AppHwPref" android:label="Applications Hardware Preferences">
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
</application>
</manifest>
diff --git a/apps/Development/res/layout/application_hw_pref.xml b/apps/Development/res/layout/application_hw_pref.xml
new file mode 100755
index 0000000..859c7ab
--- /dev/null
+++ b/apps/Development/res/layout/application_hw_pref.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="4dip" >
+
+ <TextView android:id="@+id/attr_package_label"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/package_label"
+ android:textStyle="bold" />
+ <TextView android:id="@+id/attr_package"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"/>
+
+ <TextView android:id="@+id/attr_touchscreen_label"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/touchscreen_label"
+ android:textStyle="bold" />
+ <TextView android:id="@+id/attr_touchscreen"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"/>
+
+ <TextView android:id="@+id/attr_input_method_label"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/input_method_label"
+ android:textStyle="bold" />
+ <TextView android:id="@+id/attr_input_method"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"/>
+
+ <TextView android:id="@+id/attr_hard_keyboard_label"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/hard_keyboard_label"
+ android:textStyle="bold" />
+ <TextView android:id="@+id/attr_hard_keyboard"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"/>
+
+ <TextView android:id="@+id/attr_navigation_label"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/navigation_label"
+ android:textStyle="bold" />
+ <TextView android:id="@+id/attr_navigation"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"/>
+
+ <TextView android:id="@+id/attr_five_way_nav_label"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/five_way_nav_label"
+ android:textStyle="bold" />
+ <TextView android:id="@+id/attr_five_way_nav"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"/>
+ </LinearLayout>
+</ScrollView>
+
diff --git a/apps/Development/res/layout/development_settings.xml b/apps/Development/res/layout/development_settings.xml
index 86fedcf..0486748 100644
--- a/apps/Development/res/layout/development_settings.xml
+++ b/apps/Development/res/layout/development_settings.xml
@@ -48,17 +48,10 @@
android:layout_alignParentLeft="true"
android:text="@string/development_settings_wait_for_debugger_text" />
- <CheckBox android:id="@+id/enable_adb"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/wait_for_debugger"
- android:layout_alignParentLeft="true"
- android:text="@string/development_settings_enable_adb_text" />
-
<View android:id="@+id/separator"
android:layout_width="8dip"
android:layout_height="8dip"
- android:layout_below="@id/enable_adb"
+ android:layout_below="@id/wait_for_debugger"
android:layout_alignParentLeft="true" />
<CheckBox android:id="@+id/show_load"
@@ -122,17 +115,10 @@
android:layout_alignParentLeft="true"
android:text="@string/development_settings_show_sleep_text" />
- <CheckBox android:id="@+id/keep_screen_on"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/show_sleep"
- android:layout_alignParentLeft="true"
- android:text="@string/development_settings_keep_screen_on_text" />
-
<Spinner android:id="@+id/window_animation_scale"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:layout_below="@id/keep_screen_on"
+ android:layout_below="@id/show_sleep"
android:layout_alignParentLeft="true">
</Spinner>
diff --git a/apps/Development/res/layout/gls_tester.xml b/apps/Development/res/layout/gls_tester.xml
index b6dc869..fbd4549 100644
--- a/apps/Development/res/layout/gls_tester.xml
+++ b/apps/Development/res/layout/gls_tester.xml
@@ -4,9 +4,9 @@
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.
@@ -38,13 +38,33 @@
android:text="@string/gls_tester_require_google"/>
<Button
+ android:id="@+id/get_accounts"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/gls_tester_get_accounts"/>
+
+ <Button
android:id="@+id/clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/gls_tester_clear"/>
+ <Button android:id="@+id/go"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/gls_tester_go"/>
+
</LinearLayout>
+ <EditText android:id="@+id/username_edit"
+ android:singleLine="true"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:minWidth="250dip"
+ android:scrollHorizontally="true"
+ android:capitalize="none"
+ android:autoText="false"/>
+
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
diff --git a/apps/Development/res/layout/process_info.xml b/apps/Development/res/layout/process_info.xml
new file mode 100755
index 0000000..b25f223
--- /dev/null
+++ b/apps/Development/res/layout/process_info.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="4dip" >
+
+ <TextView android:id="@+id/process_name_header"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/process_name_header"
+ android:textStyle="bold" />
+ <TextView android:id="@+id/process_name"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
+ <TextView android:id="@+id/package_list_header"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/package_list_header"
+ android:textStyle="bold" />
+
+ <LinearLayout android:id="@+id/package_list"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingTop="4dip"
+ android:paddingBottom="6dip"
+ android:paddingRight="4dip" />
+
+ </LinearLayout>
+</ScrollView>
+
diff --git a/apps/Development/res/values/strings.xml b/apps/Development/res/values/strings.xml
index 878e95f..8d343ae 100644
--- a/apps/Development/res/values/strings.xml
+++ b/apps/Development/res/values/strings.xml
@@ -21,10 +21,10 @@
<string name="menu_upload_exceptions">Upload Exceptions</string>
<string name="menu_clear_exceptions">Clear Exceptions</string>
- <string name="device_info_default">unknown</string>
- <string name="device_info_uptime">Uptime</string>
- <string name="device_info_awaketime">Awake Time</string>
- <string name="device_info_asleeptime">Asleep Time</string>
+ <string name="device_info_default">unknown</string>
+ <string name="device_info_uptime">Uptime</string>
+ <string name="device_info_awaketime">Awake Time</string>
+ <string name="device_info_asleeptime">Asleep Time</string>
<string name="build_id_label">Build ID</string>
<string name="build_date_label">Build Date</string>
@@ -78,7 +78,7 @@
<string name="development_settings_show_load_text">Show running processes</string>
<string name="development_settings_show_updates_text">Show screen updates</string>
<string name="development_settings_enable_gl_text">Enable OpenGL ES (reboot needed)</string>
- <string name="development_settings_enable_adb_text">Enable ADB</string>
+ <string name="development_settings_allow_mock_location_text">Allow mock locations for testing</string>
<string name="development_settings_wait_for_debugger_text">Wait for debugger</string>
<string name="development_settings_show_background_text">Show background</string>
<string name="development_settings_show_xmpp_text">Show GTalk service connection status</string>
@@ -105,11 +105,22 @@
<string name="red_button_behavior_label">End Button Behavior</string>
<string name="gls_tester_label">GLS Tester</string>
- <string name="gls_tester_prefer_hosted">Prefer Hosted</string>
- <string name="gls_tester_require_google">Require Google</string>
+ <string name="gls_tester_prefer_hosted">Hosted</string>
+ <string name="gls_tester_require_google">Google</string>
+ <string name="gls_tester_get_accounts">List</string>
<string name="gls_tester_clear">Clear</string>
+ <string name="gls_tester_go">Go</string>
<string name="gls_tester_do_notification">Notify on failure</string>
<string name="gls_tester_run_intent">Run intent</string>
<string name="gls_tester_wipe_passwords">Wipe passwords</string>
+ <string name="process_name_header">Process Name:</string>
+ <string name="package_list_header">Packages in process:</string>
+ <string name="package_label">Package Name:</string>
+ <!-- Application configuration requirements related attributes -->
+ <string name="touchscreen_label">touchscreen:</string>
+ <string name="input_method_label">inputMethod:</string>
+ <string name="hard_keyboard_label">hardKeyboard:</string>
+ <string name="navigation_label">navigation:</string>
+ <string name="five_way_nav_label">five way nav:</string>
</resources>
diff --git a/apps/Development/src/com/android/development/AppHwConfigList.java b/apps/Development/src/com/android/development/AppHwConfigList.java
new file mode 100755
index 0000000..52aff0d
--- /dev/null
+++ b/apps/Development/src/com/android/development/AppHwConfigList.java
@@ -0,0 +1,156 @@
+/*
+**
+** Copyright 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.development;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.LayoutInflater;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+public class AppHwConfigList extends ListActivity {
+ private static final String TAG = "AppHwConfigList";
+ PackageManager mPm;
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ mPm = getPackageManager();
+ mAdapter = new AppListAdapter(this);
+ if (mAdapter.getCount() <= 0) {
+ finish();
+ } else {
+ setListAdapter(mAdapter);
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ }
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ PackageInfo app = mAdapter.appForPosition(position);
+ // TODO display all preference settings
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setClass(this, AppHwPref.class);
+ intent.putExtra("packageName", app.packageName);
+ startActivity(intent);
+ }
+
+ private final class AppListAdapter extends BaseAdapter {
+ public AppListAdapter(Context context) {
+ mContext = context;
+ mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ List<ApplicationInfo> appList = mPm.getInstalledApplications(0);
+ for (ApplicationInfo app : appList) {
+ PackageInfo pkgInfo = null;
+ try {
+ pkgInfo = mPm.getPackageInfo(app.packageName, 0);
+ } catch (NameNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ if ((pkgInfo != null)) {
+ if(mList == null) {
+ mList = new ArrayList<PackageInfo>();
+ }
+ mList.add(pkgInfo);
+ }
+ }
+ if (mList != null) {
+ Collections.sort(mList, sDisplayNameComparator);
+ }
+ }
+
+ public PackageInfo appForPosition(int position) {
+ if (mList == null) {
+ return null;
+ }
+ return mList.get(position);
+ }
+
+ public int getCount() {
+ return mList != null ? mList.size() : 0;
+ }
+
+ public Object getItem(int position) {
+ return position;
+ }
+
+ public long getItemId(int position) {
+ return position;
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View view;
+ if (convertView == null) {
+ view = mInflater.inflate(
+ android.R.layout.simple_list_item_1, parent, false);
+ } else {
+ view = convertView;
+ }
+ bindView(view, mList.get(position));
+ return view;
+ }
+
+ private final void bindView(View view, PackageInfo info) {
+ TextView text = (TextView)view.findViewById(android.R.id.text1);
+ text.setText(info != null ? info.applicationInfo.loadLabel(mPm) : "(none)");
+ }
+
+ protected final Context mContext;
+ protected final LayoutInflater mInflater;
+ protected List<PackageInfo> mList;
+
+ }
+
+ private final Comparator sDisplayNameComparator = new Comparator() {
+ public final int compare(Object a, Object b) {
+ CharSequence sa = ((PackageInfo) a).applicationInfo.loadLabel(mPm);
+ CharSequence sb = ((PackageInfo) b).applicationInfo.loadLabel(mPm);
+ return collator.compare(sa, sb);
+ }
+ private final Collator collator = Collator.getInstance();
+ };
+
+ private AppListAdapter mAdapter;
+}
+
diff --git a/apps/Development/src/com/android/development/AppHwPref.java b/apps/Development/src/com/android/development/AppHwPref.java
new file mode 100644
index 0000000..bf0f84f
--- /dev/null
+++ b/apps/Development/src/com/android/development/AppHwPref.java
@@ -0,0 +1,228 @@
+/*
+**
+** Copyright 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.development;
+
+import com.android.development.R;
+import android.app.Activity;
+import android.app.ListActivity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ConfigurationInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.LayoutInflater;
+import android.widget.BaseAdapter;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.TextView;
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+
+/* This activity displays the hardware configuration details
+ * of an application as defined in its manifests
+ */
+public class AppHwPref extends Activity {
+ private static final String TAG = "AppHwPref";
+ PackageManager mPm;
+ private static final int BASE = 0;
+ private static final int TOUCHSCREEN = BASE + 1;
+ private static final int KEYBOARD_TYPE = BASE + 2;
+ private static final int NAVIGATION = BASE + 3;
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ Intent intent = getIntent();
+ String pkgName = intent.getStringExtra("packageName");
+ if(pkgName == null) {
+ handleError("Null package name", true);
+ return;
+ }
+ mPm = getPackageManager();
+ PackageInfo pInfo;
+ try {
+ pInfo = mPm.getPackageInfo(pkgName, PackageManager.GET_CONFIGURATIONS);
+ } catch (NameNotFoundException e) {
+ pInfo = null;
+ }
+ if(pInfo == null) {
+ handleError("Failed retrieving packageInfo for pkg:"+pkgName, true);
+ return;
+ }
+ ConfigurationInfo appHwPref[] = pInfo.configPreferences;
+
+ setContentView(R.layout.application_hw_pref);
+ if(appHwPref != null) {
+ displayTextView(R.id.attr_package, pInfo.applicationInfo.loadLabel(mPm));
+ displayTextView(R.id.attr_touchscreen, appHwPref, TOUCHSCREEN);
+ displayTextView(R.id.attr_input_method, appHwPref, KEYBOARD_TYPE);
+ displayTextView(R.id.attr_navigation, appHwPref, NAVIGATION);
+ displayFlag(R.id.attr_hard_keyboard, ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD, appHwPref);
+ displayFlag(R.id.attr_five_way_nav, ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV, appHwPref);
+ }
+ }
+
+ void displayFlag(int viewId, int flagMask, ConfigurationInfo[] appHwPref) {
+ if(appHwPref == null) {
+ return;
+ }
+ boolean flag = false;
+ for (int i = 0; i < appHwPref.length; i++) {
+ ConfigurationInfo pref = appHwPref[i];
+ if((pref.reqInputFeatures & flagMask) != 0) {
+ flag = true;
+ break;
+ }
+ }
+ if(flag) {
+ displayTextView(viewId, "true");
+ } else {
+ displayTextView(viewId, "false");
+ }
+ }
+
+ void handleError(String errMsg, boolean finish) {
+ // TODO display dialog
+ Log.i(TAG, errMsg);
+ if(finish) {
+ finish();
+ }
+ }
+
+ void displayTextView(int textViewId, CharSequence displayStr) {
+ TextView tView = (TextView) findViewById(textViewId);
+ if(displayStr != null) {
+ tView.setText(displayStr);
+ }
+ }
+
+ void displayTextView(int viewId, ConfigurationInfo[] config, int type) {
+ if((config == null) || (config.length < 1)) {
+ return;
+ }
+
+ HashSet<String> list = new HashSet<String>();
+ for(int i = 0; i < config.length; i++) {
+ String str = null;
+ switch(type) {
+ case TOUCHSCREEN:
+ str = getTouchScreenStr(config[i]);
+ break;
+ case KEYBOARD_TYPE:
+ str = getKeyboardTypeStr(config[i]);
+ break;
+ case NAVIGATION:
+ str = getNavigationStr(config[i]);
+ break;
+ }
+ if(str != null) {
+ list.add(str);
+ }
+ }
+ String listStr = "";
+ boolean set = false;
+ for(String str : list) {
+ set = true;
+ listStr += str+",";
+ }
+ if(set) {
+ TextView tView = (TextView)findViewById(viewId);
+ CharSequence txt = listStr.subSequence(0, listStr.length()-1);
+ tView.setText(txt);
+ }
+ }
+
+ String getTouchScreenStr(ConfigurationInfo appHwPref) {
+ if(appHwPref == null) {
+ handleError("Invalid HardwareConfigurationObject", true);
+ return null;
+ }
+ switch(appHwPref.reqTouchScreen) {
+ case Configuration.TOUCHSCREEN_FINGER:
+ return "finger";
+ case Configuration.TOUCHSCREEN_NOTOUCH:
+ return "notouch";
+ case Configuration.TOUCHSCREEN_STYLUS:
+ return "stylus";
+ case Configuration.TOUCHSCREEN_UNDEFINED:
+ return null;
+ default:
+ return null;
+ }
+ }
+
+ String getKeyboardTypeStr(ConfigurationInfo appHwPref) {
+ if(appHwPref == null) {
+ handleError("Invalid HardwareConfigurationObject", true);
+ return null;
+ }
+ switch(appHwPref.reqKeyboardType) {
+ case Configuration.KEYBOARD_12KEY:
+ return "12key";
+ case Configuration.KEYBOARD_NOKEYS:
+ return "nokeys";
+ case Configuration.KEYBOARD_QWERTY:
+ return "querty";
+ case Configuration.KEYBOARD_UNDEFINED:
+ return null;
+ default:
+ return null;
+ }
+ }
+
+ String getNavigationStr(ConfigurationInfo appHwPref) {
+ if(appHwPref == null) {
+ handleError("Invalid HardwareConfigurationObject", true);
+ return null;
+ }
+ switch(appHwPref.reqNavigation) {
+ case Configuration.NAVIGATION_DPAD:
+ return "dpad";
+ case Configuration.NAVIGATION_TRACKBALL:
+ return "trackball";
+ case Configuration.NAVIGATION_WHEEL:
+ return "wheel";
+ case Configuration.NAVIGATION_UNDEFINED:
+ return null;
+ default:
+ return null;
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ }
+}
+
diff --git a/apps/Development/src/com/android/development/DevelopmentSettings.java b/apps/Development/src/com/android/development/DevelopmentSettings.java
index 03536bb..cdc1e0a 100644
--- a/apps/Development/src/com/android/development/DevelopmentSettings.java
+++ b/apps/Development/src/com/android/development/DevelopmentSettings.java
@@ -49,7 +49,6 @@
private static final int DEBUG_APP_REQUEST = 1;
private Button mDebugAppButton;
- private CheckBox mEnableAdbCB;
private CheckBox mWaitForDebuggerCB;
private CheckBox mAlwaysFinishCB;
private CheckBox mShowLoadCB;
@@ -59,7 +58,6 @@
private CheckBox mShowBackgroundCB;
private CheckBox mShowSleepCB;
private CheckBox mShowMapsCompassCB;
- private CheckBox mKeepScreenOnCB;
private CheckBox mShowXmppCB;
private Spinner mMaxProcsSpinner;
private Spinner mWindowAnimationScaleSpinner;
@@ -67,13 +65,11 @@
private Spinner mFontHintingSpinner;
private String mDebugApp;
- private boolean mEnableAdb;
private boolean mWaitForDebugger;
private boolean mAlwaysFinish;
private int mProcessLimit;
private boolean mShowSleep;
private boolean mShowMapsCompass;
- private boolean mKeepScreenOn;
private boolean mShowXmpp;
private AnimationScaleSelectedListener mWindowAnimationScale
= new AnimationScaleSelectedListener(0);
@@ -93,8 +89,6 @@
mDebugAppButton = (Button)findViewById(R.id.debug_app);
mDebugAppButton.setOnClickListener(mDebugAppClicked);
- mEnableAdbCB = (CheckBox)findViewById(R.id.enable_adb);
- mEnableAdbCB.setOnClickListener(mEnableAdbClicked);
mWaitForDebuggerCB = (CheckBox)findViewById(R.id.wait_for_debugger);
mWaitForDebuggerCB.setOnClickListener(mWaitForDebuggerClicked);
mAlwaysFinishCB = (CheckBox)findViewById(R.id.always_finish);
@@ -114,8 +108,6 @@
mShowSleepCB.setOnClickListener(mShowSleepClicked);
mShowMapsCompassCB = (CheckBox)findViewById(R.id.show_maps_compass);
mShowMapsCompassCB.setOnClickListener(mShowMapsCompassClicked);
- mKeepScreenOnCB = (CheckBox)findViewById(R.id.keep_screen_on);
- mKeepScreenOnCB.setOnClickListener(mKeepScreenOnClicked);
mShowXmppCB = (CheckBox)findViewById(R.id.show_xmpp);
mShowXmppCB.setOnClickListener(mShowXmppClicked);
mMaxProcsSpinner = (Spinner)findViewById(R.id.max_procs);
@@ -181,7 +173,6 @@
updateFlingerOptions();
updateSleepOptions();
updateMapsCompassOptions();
- updateKeepScreenOnOptions();
updateXmppOptions();
try {
@@ -210,13 +201,10 @@
getContentResolver(), Settings.System.DEBUG_APP);
mWaitForDebugger = Settings.System.getInt(
getContentResolver(), Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
- mEnableAdb = Settings.System.getInt(
- getContentResolver(), Settings.System.ADB_ENABLED, 0) != 0;
mDebugAppButton.setText(
mDebugApp == null || mDebugApp.length() == 0 ? "(none)" : mDebugApp);
mWaitForDebuggerCB.setChecked(mWaitForDebugger);
- mEnableAdbCB.setChecked(mEnableAdb);
}
private void writeFinishOptions() {
@@ -330,17 +318,6 @@
mShowMapsCompassCB.setChecked(mShowMapsCompass);
}
- private void writeKeepScreenOnOptions() {
- Settings.System.putInt(getContentResolver(), Settings.System.STAY_ON_WHILE_PLUGGED_IN,
- mKeepScreenOn ? 1 : 0);
- }
-
- private void updateKeepScreenOnOptions() {
- mKeepScreenOn = Settings.System.getInt(getContentResolver(),
- Settings.System.STAY_ON_WHILE_PLUGGED_IN, 0) != 0;
- mKeepScreenOnCB.setChecked(mKeepScreenOn);
- }
-
private void writeXmppOptions() {
Settings.System.setShowGTalkServiceStatus(getContentResolver(), mShowXmpp);
}
@@ -367,13 +344,6 @@
}
}
- private View.OnClickListener mEnableAdbClicked = new View.OnClickListener() {
- public void onClick(View v) {
- Settings.System.putInt(getContentResolver(), Settings.System.ADB_ENABLED,
- ((CheckBox)v).isChecked() ? 1 : 0);
- }
- };
-
private View.OnClickListener mWaitForDebuggerClicked =
new View.OnClickListener() {
public void onClick(View v) {
@@ -450,15 +420,6 @@
};
- private View.OnClickListener mKeepScreenOnClicked =
- new View.OnClickListener() {
- public void onClick(View v) {
- mKeepScreenOn = ((CheckBox)v).isChecked();
- writeKeepScreenOnOptions();
- updateKeepScreenOnOptions();
- }
- };
-
private View.OnClickListener mShowXmppClicked = new View.OnClickListener() {
public void onClick(View v) {
mShowXmpp = ((CheckBox)v).isChecked();
diff --git a/apps/Development/src/com/android/development/EnterURL.java b/apps/Development/src/com/android/development/EnterURL.java
index 72f58de..76b8a34 100644
--- a/apps/Development/src/com/android/development/EnterURL.java
+++ b/apps/Development/src/com/android/development/EnterURL.java
@@ -24,9 +24,9 @@
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Bundle;
-import android.pim.DateUtils;
import android.text.Editable;
import android.text.Selection;
+import android.text.format.DateUtils;
import android.util.AttributeSet;
import android.view.Menu;
import android.view.MenuItem;
diff --git a/apps/Development/src/com/android/development/GLSTester.java b/apps/Development/src/com/android/development/GLSTester.java
index 57b8120..4995b4d 100644
--- a/apps/Development/src/com/android/development/GLSTester.java
+++ b/apps/Development/src/com/android/development/GLSTester.java
@@ -27,12 +27,13 @@
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
-import android.os.RemoteException;
import android.os.IBinder;
+import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
+import android.widget.EditText;
import android.widget.Spinner;
/**
@@ -52,12 +53,10 @@
CheckBox mDoNotify = null;
CheckBox mRunIntent = null;
Spinner mService = null;
+ EditText mUsernameEdit = null;
private class Listener implements View.OnClickListener {
- private boolean mRequireGoogle;
-
- public Listener(boolean requireGoogle) {
- mRequireGoogle = requireGoogle;
+ public Listener() {
}
public void onClick(View v) {
@@ -69,7 +68,10 @@
String service = (String) mService.getSelectedItem();
mText.append("service: " + service + "\n");
- String account = mGls.getAccount(mRequireGoogle);
+ String account = mUsernameEdit.getText().toString();
+ if (account.length() == 0) {
+ account = null;
+ }
mText.append("account: " + account + "\n");
GoogleLoginCredentialsResult result =
mGls.blockingGetCredentials(account, service, mDoNotify.isChecked());
@@ -120,6 +122,8 @@
setContentView(R.layout.gls_tester);
mText = (LogTextBox) findViewById(R.id.text);
+ mText.append("Hello, world!\n");
+ Log.v(TAG, "hello, world!");
mDoNotify = (CheckBox) findViewById(R.id.do_notification);
mRunIntent = (CheckBox) findViewById(R.id.run_intent);
@@ -127,11 +131,47 @@
mService = (Spinner) findViewById(R.id.service_spinner);
+ mUsernameEdit = (EditText) findViewById(R.id.username_edit);
+
Button b;
b = (Button) findViewById(R.id.require_google);
- b.setOnClickListener(new Listener(GoogleLoginServiceConstants.REQUIRE_GOOGLE));
+ b.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ try {
+ String account = mGls.getAccount(GoogleLoginServiceConstants.REQUIRE_GOOGLE);
+ mText.append("REQUIRE_GOOGLE gave: " + account + "\n");
+ mUsernameEdit.setText(account == null ? "" : account);
+ } catch (RemoteException e) {
+ mText.append("exception: " + e + "\n");
+ }
+ } });
+
b = (Button) findViewById(R.id.prefer_hosted);
- b.setOnClickListener(new Listener(GoogleLoginServiceConstants.PREFER_HOSTED));
+ b.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ try {
+ String account = mGls.getAccount(GoogleLoginServiceConstants.PREFER_HOSTED);
+ mText.append("PREFER_HOSTED gave: " + account + "\n");
+ mUsernameEdit.setText(account == null ? "" : account);
+ } catch (RemoteException e) {
+ mText.append("exception: " + e + "\n");
+ }
+ } });
+
+
+ b = (Button) findViewById(R.id.get_accounts);
+ b.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ try {
+ String[] accounts = mGls.getAccounts();
+ mText.append("account list: (" + accounts.length + " entries)\n");
+ for (String username: accounts) {
+ mText.append(" " + username + "\n");
+ }
+ } catch (RemoteException e) {
+ mText.append("exception: " + e + "\n");
+ }
+ } });
b = (Button) findViewById(R.id.clear);
b.setOnClickListener(new View.OnClickListener() {
@@ -139,6 +179,9 @@
mText.setText("");
} });
+ b = (Button) findViewById(R.id.go);
+ b.setOnClickListener(new Listener());
+
b = (Button) findViewById(R.id.wipe_passwords);
b.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
diff --git a/apps/Development/src/com/android/development/ProcessInfo.java b/apps/Development/src/com/android/development/ProcessInfo.java
new file mode 100755
index 0000000..5ece1a4
--- /dev/null
+++ b/apps/Development/src/com/android/development/ProcessInfo.java
@@ -0,0 +1,62 @@
+/*
+**
+** Copyright 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.development;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+public class ProcessInfo extends Activity {
+ PackageManager mPm;
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ Intent intent = getIntent();
+ String processName = intent.getStringExtra("processName");
+ String pkgList[] = intent.getStringArrayExtra("packageList");
+ mPm = getPackageManager();
+ setContentView(R.layout.process_info);
+ TextView processNameView = (TextView) findViewById(R.id.process_name);
+ LinearLayout pkgListView = (LinearLayout) findViewById(R.id.package_list);
+ if(processName != null) {
+ processNameView.setText(processName);
+ }
+ if(pkgList != null) {
+ for(String pkg : pkgList) {
+ TextView pkgView = new TextView(this);
+ pkgView.setText(pkg);
+ pkgListView.addView(pkgView);
+ }
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ }
+}
+
diff --git a/apps/Development/src/com/android/development/RadioIssueReport.java b/apps/Development/src/com/android/development/RadioIssueReport.java
index e1d1ec8..b1a95f4 100644
--- a/apps/Development/src/com/android/development/RadioIssueReport.java
+++ b/apps/Development/src/com/android/development/RadioIssueReport.java
@@ -19,11 +19,11 @@
import android.app.Activity;
import android.os.Bundle;
import android.os.SystemProperties;
-import android.pim.DateFormat;
import android.provider.Checkin;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import android.telephony.ServiceState;
+import android.text.format.DateFormat;
import static com.android.internal.util.CharSequences.forAsciiBytes;
import android.util.Log;
import android.view.View.OnClickListener;
diff --git a/apps/Development/src/com/android/development/RunningProcesses.java b/apps/Development/src/com/android/development/RunningProcesses.java
new file mode 100755
index 0000000..7b56be9
--- /dev/null
+++ b/apps/Development/src/com/android/development/RunningProcesses.java
@@ -0,0 +1,154 @@
+/*
+**
+** Copyright 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.development;
+
+import android.app.ActivityManager;
+import android.app.ListActivity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.LayoutInflater;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+public class RunningProcesses extends ListActivity {
+ PackageManager mPm;
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ mPm = getPackageManager();
+ mAdapter = new AppListAdapter(this);
+ if (mAdapter.getCount() <= 0) {
+ finish();
+ } else {
+ setListAdapter(mAdapter);
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ }
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ ListItem app = mAdapter.appForPosition(position);
+ // Create intent to start new activity
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setClass(this, ProcessInfo.class);
+ intent.putExtra("processName", app.procInfo.processName);
+ intent.putExtra("packageList", app.procInfo.pkgList);
+ // start new activity to display extended information
+ startActivity(intent);
+ }
+
+ private final class AppListAdapter extends BaseAdapter {
+ public AppListAdapter(Context context) {
+ mContext = context;
+ mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
+ List<ActivityManager.RunningAppProcessInfo> appList = am.getRunningAppProcesses();
+ for (ActivityManager.RunningAppProcessInfo app : appList) {
+ if(mList == null) {
+ mList = new ArrayList<ListItem>();
+ }
+ mList.add(new ListItem(app));
+ }
+ if (mList != null) {
+ Collections.sort(mList, sDisplayNameComparator);
+ }
+ }
+
+ public ListItem appForPosition(int position) {
+ if (mList == null) {
+ return null;
+ }
+ return mList.get(position);
+ }
+
+ public int getCount() {
+ return mList != null ? mList.size() : 0;
+ }
+
+ public Object getItem(int position) {
+ return position;
+ }
+
+ public long getItemId(int position) {
+ return position;
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View view;
+ if (convertView == null) {
+ view = mInflater.inflate(
+ android.R.layout.simple_list_item_1, parent, false);
+ } else {
+ view = convertView;
+ }
+ bindView(view, mList.get(position));
+ return view;
+ }
+
+ private final void bindView(View view, ListItem info) {
+ TextView text = (TextView)view.findViewById(android.R.id.text1);
+ text.setText(info != null ? info.procInfo.processName : "(none)");
+ }
+
+ protected final Context mContext;
+ protected final LayoutInflater mInflater;
+ protected List<ListItem> mList;
+
+ }
+
+ private final Comparator sDisplayNameComparator = new Comparator() {
+ public final int compare(Object a, Object b) {
+ CharSequence sa = ((ListItem) a).procInfo.processName;
+ CharSequence sb = ((ListItem) b).procInfo.processName;
+ return collator.compare(sa, sb);
+ }
+ private final Collator collator = Collator.getInstance();
+ };
+
+ private class ListItem {
+ ActivityManager.RunningAppProcessInfo procInfo;
+ public ListItem(ActivityManager.RunningAppProcessInfo pInfo) {
+ procInfo = pInfo;
+ }
+ }
+
+ private AppListAdapter mAdapter;
+}
+
diff --git a/apps/Fallback/res/values-de-rDE/strings.xml b/apps/Fallback/res/values-de-rDE/strings.xml
deleted file mode 100644
index e7256ef..0000000
--- a/apps/Fallback/res/values-de-rDE/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="appTitle">Rückgriff</string>
- <string name="error">Dieser Vorgang wird derzeit nicht unterstützt.</string>
- <string name="title">Nicht unterstützter Vorgang</string>
-</resources>
diff --git a/apps/Fallback/res/values-de/strings.xml b/apps/Fallback/res/values-de/strings.xml
new file mode 100644
index 0000000..0889ced
--- /dev/null
+++ b/apps/Fallback/res/values-de/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="appTitle">"Fallback"</string>
+ <string name="title">"Nicht unterstützte Aktion"</string>
+ <string name="error">"Diese Aktion wird zurzeit nicht unterstützt."</string>
+</resources>
diff --git a/apps/Fallback/res/values-es-rUS/strings.xml b/apps/Fallback/res/values-es-rUS/strings.xml
deleted file mode 100644
index 028a9ac..0000000
--- a/apps/Fallback/res/values-es-rUS/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="appTitle">Seguridad</string>
- <string name="error">En estos momentos, la acción no es compatible.</string>
- <string name="title">Acción no compatible</string>
-</resources>
diff --git a/apps/Fallback/res/values-fr-rFR/strings.xml b/apps/Fallback/res/values-fr-rFR/strings.xml
deleted file mode 100644
index 70fc6f1..0000000
--- a/apps/Fallback/res/values-fr-rFR/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="appTitle">Secours</string>
- <string name="error">Cette action n\'est pas actuellement prise en charge.</string>
- <string name="title">Action non prise en charge</string>
-</resources>
diff --git a/apps/Fallback/res/values-it-rIT/strings.xml b/apps/Fallback/res/values-it-rIT/strings.xml
deleted file mode 100644
index 9390949..0000000
--- a/apps/Fallback/res/values-it-rIT/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="appTitle">Fallback</string>
- <string name="error">L'azione non è attualmente supportata.</string>
- <string name="title">Azione non supportata</string>
-</resources>
diff --git a/apps/Fallback/res/values-ja/strings.xml b/apps/Fallback/res/values-ja/strings.xml
new file mode 100644
index 0000000..6629b33
--- /dev/null
+++ b/apps/Fallback/res/values-ja/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="appTitle">"Fallback"</string>
+ <string name="title">"サポートされていない操作"</string>
+ <string name="error">"現在サポートされていない操作です。"</string>
+</resources>
diff --git a/apps/Fallback/res/values-zh-rTW/strings.xml b/apps/Fallback/res/values-zh-rTW/strings.xml
deleted file mode 100644
index 84a5abd..0000000
--- a/apps/Fallback/res/values-zh-rTW/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="appTitle">還原</string>
- <string name="error">目前不支援此動作。</string>
- <string name="title">不支援的動作</string>
-</resources>
diff --git a/apps/Fallback/res/values/strings.xml b/apps/Fallback/res/values/strings.xml
index d41ffd2..bc0b71d 100644
--- a/apps/Fallback/res/values/strings.xml
+++ b/apps/Fallback/res/values/strings.xml
@@ -15,7 +15,11 @@
-->
<resources>
+ <!-- Name of the fallback application. It's used only on the SDK when applications from
+ real phones aren't available. -->
<string name="appTitle">Fallback</string>
+ <!-- Dialog title informing the user that the requested action is not supported -->
<string name="title">Unsupported action</string>
+ <!-- Dialog content informing the user that the requested action is not supported -->
<string name="error">That action is not currently supported.</string>
</resources>
diff --git a/apps/SdkSetup/Android.mk b/apps/SdkSetup/Android.mk
index daab48d..b89baaf 100644
--- a/apps/SdkSetup/Android.mk
+++ b/apps/SdkSetup/Android.mk
@@ -1,7 +1,7 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := samples
+LOCAL_MODULE_TAGS := foo
LOCAL_SRC_FILES := $(call all-subdir-java-files)
diff --git a/apps/SdkSetup/AndroidManifest.xml b/apps/SdkSetup/AndroidManifest.xml
index 9bb292c..9cd20a8 100644
--- a/apps/SdkSetup/AndroidManifest.xml
+++ b/apps/SdkSetup/AndroidManifest.xml
@@ -17,8 +17,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.sdksetup">
- <!-- For miscellaneous settings -->
- <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+ <!-- For miscellaneous secure settings -->
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<application>
<activity android:name="DefaultActivity"
diff --git a/apps/SdkSetup/src/com/android/sdksetup/DefaultActivity.java b/apps/SdkSetup/src/com/android/sdksetup/DefaultActivity.java
index 37f7c00..db6385c 100644
--- a/apps/SdkSetup/src/com/android/sdksetup/DefaultActivity.java
+++ b/apps/SdkSetup/src/com/android/sdksetup/DefaultActivity.java
@@ -21,7 +21,7 @@
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.os.Bundle;
-import android.provider.Settings.System;
+import android.provider.Settings;
/**
* Entry point for SDK SetupWizard.
@@ -34,16 +34,16 @@
super.onCreate(icicle);
// Add a persistent setting to allow other apps to know the device has been provisioned.
- System.putInt(getContentResolver(), System.DEVICE_PROVISIONED, 1);
+ Settings.Secure.putInt(getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 1);
// Enable the GPS.
// Not needed since this SDK will contain the Settings app.
LocationManager locationManager = (LocationManager)getSystemService(LOCATION_SERVICE);
- System.putString(getContentResolver(), System.LOCATION_PROVIDERS_ALLOWED, LocationManager.GPS_PROVIDER);
+ Settings.Secure.putString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, LocationManager.GPS_PROVIDER);
locationManager.updateProviders();
// enable install from non market
- System.putInt(getContentResolver(), System.INSTALL_NON_MARKET_APPS, 1);
+ Settings.Secure.putInt(getContentResolver(), Settings.Secure.INSTALL_NON_MARKET_APPS, 1);
// remove this activity from the package manager.
PackageManager pm = getPackageManager();
diff --git a/apps/SpareParts/Android.mk b/apps/SpareParts/Android.mk
new file mode 100644
index 0000000..ccf6c6d
--- /dev/null
+++ b/apps/SpareParts/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := eng development
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := SpareParts
+
+include $(BUILD_PACKAGE)
diff --git a/apps/SpareParts/AndroidManifest.xml b/apps/SpareParts/AndroidManifest.xml
new file mode 100644
index 0000000..85de7a4
--- /dev/null
+++ b/apps/SpareParts/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.spare_parts">
+ <uses-permission android:name="android.permission.SET_ANIMATION_SCALE" />
+ <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
+ <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+
+ <application android:label="@string/app_label"
+ android:icon="@drawable/app_icon">
+
+ <activity android:name="SpareParts">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ </application>
+</manifest>
diff --git a/apps/SpareParts/res/drawable/app_icon.png b/apps/SpareParts/res/drawable/app_icon.png
new file mode 100644
index 0000000..cb40a19
--- /dev/null
+++ b/apps/SpareParts/res/drawable/app_icon.png
Binary files differ
diff --git a/apps/SpareParts/res/layout/spare_parts.xml b/apps/SpareParts/res/layout/spare_parts.xml
new file mode 100644
index 0000000..f39298b
--- /dev/null
+++ b/apps/SpareParts/res/layout/spare_parts.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/Settings/assets/res/any/layout/keyboard_version.xml
+**
+** Copyright 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.
+*/
+-->
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <RelativeLayout
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <Spinner android:id="@+id/window_animation_scale"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true">
+ </Spinner>
+
+ <Spinner android:id="@+id/transition_animation_scale"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/window_animation_scale"
+ android:layout_alignParentLeft="true">
+ </Spinner>
+
+ <CheckBox android:id="@+id/show_maps_compass"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/transition_animation_scale"
+ android:layout_alignParentLeft="true"
+ android:text="@string/development_settings_show_maps_compass_text" />
+
+ </RelativeLayout>
+
+</ScrollView>
+
diff --git a/apps/SpareParts/res/values/arrays.xml b/apps/SpareParts/res/values/arrays.xml
new file mode 100644
index 0000000..e6026da
--- /dev/null
+++ b/apps/SpareParts/res/values/arrays.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * 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.
+ -->
+
+<resources>
+ <string-array name="entries_animations">
+ <item>Off</item>
+ <item>Fast</item>
+ <item>Normal</item>
+ <item>Slow</item>
+ <item>Very Slow</item>
+ </string-array>
+
+ <string-array name="entryvalues_animations">
+ <item>0.0</item>
+ <item>0.5</item>
+ <item>1.0</item>
+ <item>1.5</item>
+ <item>2.0</item>
+ </string-array>
+
+ <string-array name="entries_font_size">
+ <item>Extremely Small</item>
+ <item>Extra Small</item>
+ <item>Small</item>
+ <item>Normal</item>
+ <item>Large</item>
+ <item>Extra Large</item>
+ <item>Extremely Large</item>
+ </string-array>
+
+ <string-array name="entryvalues_font_size">
+ <item>0.70</item>
+ <item>0.85</item>
+ <item>0.95</item>
+ <item>1.0</item>
+ <item>1.05</item>
+ <item>1.15</item>
+ <item>1.30</item>
+ </string-array>
+
+ <string-array name="entries_end_button">
+ <item>Nothing</item>
+ <item>Go to home</item>
+ <item>Go to sleep</item>
+ <item>Home, then sleep</item>
+ </string-array>
+
+ <string-array name="entryvalues_end_button">
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ <item>3</item>
+ </string-array>
+</resources>
diff --git a/apps/SpareParts/res/values/strings.xml b/apps/SpareParts/res/values/strings.xml
new file mode 100644
index 0000000..8565a52
--- /dev/null
+++ b/apps/SpareParts/res/values/strings.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 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.
+*/
+-->
+<resources>
+ <string name="app_label">Spare Parts</string>
+
+ <string name="general_title">General</string>
+
+ <string name="title_window_animations">Window animations</string>
+ <string name="summary_window_animations">Speed of animations in individual windows</string>
+ <string name="dialog_title_window_animations">Select window speed</string>
+
+ <string name="title_transition_animations">Transition animations</string>
+ <string name="summary_transition_animations">Speed of animations moving between screens</string>
+ <string name="dialog_title_transition_animations">Select transition speed</string>
+
+ <string name="title_font_size">Font size</string>
+ <string name="summary_font_size">Overall size of fonts</string>
+ <string name="dialog_title_font_size">Select font size</string>
+
+ <string name="title_end_button">End button behavior</string>
+ <string name="summary_end_button">Select End (red) button action</string>
+ <string name="dialog_title_end_button">Select End button</string>
+
+ <string name="title_accelerometer">Display rotation</string>
+ <string name="summary_on_accelerometer">Display rotates from orientation</string>
+ <string name="summary_off_accelerometer">Display rotates when lid is open</string>
+
+ <string name="applications_title">Applications</string>
+
+ <string name="title_maps_compass">Show compass in Maps</string>
+ <string name="summary_on_maps_compass">Compass is displayed in Maps</string>
+ <string name="summary_off_maps_compass">Compass is not displayed in Maps</string>
+
+ <string name="development_settings_show_maps_compass_text">Show compass in Maps</string>
+</resources>
diff --git a/apps/SpareParts/res/xml/spare_parts.xml b/apps/SpareParts/res/xml/spare_parts.xml
new file mode 100644
index 0000000..ce673e3
--- /dev/null
+++ b/apps/SpareParts/res/xml/spare_parts.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+ * Copyright 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.
+ */
+-->
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <PreferenceCategory
+ android:title="@string/general_title">
+
+ <ListPreference
+ android:key="window_animations"
+ android:title="@string/title_window_animations"
+ android:summary="@string/summary_window_animations"
+ android:entries="@array/entries_animations"
+ android:entryValues="@array/entryvalues_animations"
+ android:dialogTitle="@string/dialog_title_window_animations" />
+
+ <ListPreference
+ android:key="transition_animations"
+ android:title="@string/title_transition_animations"
+ android:summary="@string/summary_transition_animations"
+ android:entries="@array/entries_animations"
+ android:entryValues="@array/entryvalues_animations"
+ android:dialogTitle="@string/dialog_title_transition_animations" />
+
+ <ListPreference
+ android:key="font_size"
+ android:title="@string/title_font_size"
+ android:summary="@string/summary_font_size"
+ android:entries="@array/entries_font_size"
+ android:entryValues="@array/entryvalues_font_size"
+ android:dialogTitle="@string/dialog_title_font_size" />
+
+ <ListPreference
+ android:key="end_button"
+ android:title="@string/title_end_button"
+ android:summary="@string/summary_end_button"
+ android:entries="@array/entries_end_button"
+ android:entryValues="@array/entryvalues_end_button"
+ android:dialogTitle="@string/dialog_title_end_button" />
+
+ <CheckBoxPreference
+ android:key="accelerometer"
+ android:title="@string/title_accelerometer"
+ android:summaryOn="@string/summary_on_accelerometer"
+ android:summaryOff="@string/summary_off_accelerometer"/>
+
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:title="@string/applications_title">
+
+ <CheckBoxPreference
+ android:key="maps_compass"
+ android:title="@string/title_maps_compass"
+ android:summaryOn="@string/summary_on_maps_compass"
+ android:summaryOff="@string/summary_off_maps_compass"/>
+
+ </PreferenceCategory>
+
+</PreferenceScreen>
diff --git a/apps/SpareParts/src/com/android/spare_parts/SpareParts.java b/apps/SpareParts/src/com/android/spare_parts/SpareParts.java
new file mode 100644
index 0000000..9de9a45
--- /dev/null
+++ b/apps/SpareParts/src/com/android/spare_parts/SpareParts.java
@@ -0,0 +1,207 @@
+/* //device/apps/Settings/src/com/android/settings/Keyguard.java
+**
+** Copyright 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.spare_parts;
+
+import android.app.ActivityManagerNative;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Configuration;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+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.os.Bundle;
+import android.util.Log;
+import android.view.IWindowManager;
+
+public class SpareParts extends PreferenceActivity
+ implements Preference.OnPreferenceChangeListener,
+ SharedPreferences.OnSharedPreferenceChangeListener {
+ private static final String TAG = "SpareParts";
+
+ private static final String WINDOW_ANIMATIONS_PREF = "window_animations";
+ private static final String TRANSITION_ANIMATIONS_PREF = "transition_animations";
+ private static final String FONT_SIZE_PREF = "font_size";
+ private static final String END_BUTTON_PREF = "end_button";
+ private static final String ACCELEROMETER_PREF = "accelerometer";
+ private static final String MAPS_COMPASS_PREF = "maps_compass";
+
+ private final Configuration mCurConfig = new Configuration();
+
+ private ListPreference mWindowAnimationsPref;
+ private ListPreference mTransitionAnimationsPref;
+ private ListPreference mFontSizePref;
+ private ListPreference mEndButtonPref;
+ private CheckBoxPreference mAccelerometerPref;
+ private CheckBoxPreference mShowMapsCompassPref;
+
+ private IWindowManager mWindowManager;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ addPreferencesFromResource(R.xml.spare_parts);
+
+ PreferenceScreen prefSet = getPreferenceScreen();
+
+ mWindowAnimationsPref = (ListPreference) prefSet.findPreference(WINDOW_ANIMATIONS_PREF);
+ mWindowAnimationsPref.setOnPreferenceChangeListener(this);
+ mTransitionAnimationsPref = (ListPreference) prefSet.findPreference(TRANSITION_ANIMATIONS_PREF);
+ mTransitionAnimationsPref.setOnPreferenceChangeListener(this);
+ mFontSizePref = (ListPreference) prefSet.findPreference(FONT_SIZE_PREF);
+ mFontSizePref.setOnPreferenceChangeListener(this);
+ mEndButtonPref = (ListPreference) prefSet.findPreference(END_BUTTON_PREF);
+ mEndButtonPref.setOnPreferenceChangeListener(this);
+ mAccelerometerPref = (CheckBoxPreference) prefSet.findPreference(ACCELEROMETER_PREF);
+ mShowMapsCompassPref = (CheckBoxPreference) prefSet.findPreference(MAPS_COMPASS_PREF);
+
+ mWindowManager = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
+
+ getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
+ }
+
+ private void updateToggles() {
+ try {
+ mAccelerometerPref.setChecked(Settings.System.getInt(
+ getContentResolver(),
+ Settings.System.ACCELEROMETER_ROTATION, 0) != 0);
+ Context c = createPackageContext("com.google.android.apps.maps", 0);
+ mShowMapsCompassPref.setChecked(c.getSharedPreferences("extra-features", MODE_WORLD_READABLE)
+ .getBoolean("compass", false));
+ } catch (NameNotFoundException e) {
+ Log.w(TAG, "Failed reading maps compass");
+ e.printStackTrace();
+ }
+ }
+
+ public boolean onPreferenceChange(Preference preference, Object objValue) {
+ if (preference == mWindowAnimationsPref) {
+ writeAnimationPreference(0, objValue);
+ } else if (preference == mTransitionAnimationsPref) {
+ writeAnimationPreference(1, objValue);
+ } else if (preference == mFontSizePref) {
+ writeFontSizePreference(objValue);
+ } else if (preference == mEndButtonPref) {
+ writeEndButtonPreference(objValue);
+ }
+
+ // always let the preference setting proceed.
+ return true;
+ }
+
+ public void writeAnimationPreference(int which, Object objValue) {
+ try {
+ float val = Float.parseFloat(objValue.toString());
+ mWindowManager.setAnimationScale(which, val);
+ } catch (NumberFormatException e) {
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void writeFontSizePreference(Object objValue) {
+ try {
+ mCurConfig.fontScale = Float.parseFloat(objValue.toString());
+ ActivityManagerNative.getDefault().updateConfiguration(mCurConfig);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void writeEndButtonPreference(Object objValue) {
+ try {
+ int val = Integer.parseInt(objValue.toString());
+ Settings.System.putInt(getContentResolver(),
+ Settings.System.END_BUTTON_BEHAVIOR, val);
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ int floatToIndex(float val, int resid) {
+ String[] indices = getResources().getStringArray(resid);
+ float lastVal = Float.parseFloat(indices[0]);
+ for (int i=1; i<indices.length; i++) {
+ float thisVal = Float.parseFloat(indices[i]);
+ if (val < (lastVal + (thisVal-lastVal)*.5f)) {
+ return i-1;
+ }
+ lastVal = thisVal;
+ }
+ return indices.length-1;
+ }
+
+ public void readAnimationPreference(int which, ListPreference pref) {
+ try {
+ float scale = mWindowManager.getAnimationScale(which);
+ pref.setValueIndex(floatToIndex(scale,
+ R.array.entryvalues_animations));
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void readFontSizePreference(ListPreference pref) {
+ try {
+ mCurConfig.updateFrom(
+ ActivityManagerNative.getDefault().getConfiguration());
+ } catch (RemoteException e) {
+ }
+ pref.setValueIndex(floatToIndex(mCurConfig.fontScale,
+ R.array.entryvalues_font_size));
+ }
+
+ public void readEndButtonPreference(ListPreference pref) {
+ try {
+ pref.setValueIndex(Settings.System.getInt(getContentResolver(),
+ Settings.System.END_BUTTON_BEHAVIOR));
+ } catch (SettingNotFoundException e) {
+ }
+ }
+
+ public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
+ if (ACCELEROMETER_PREF.equals(key)) {
+ Settings.System.putInt(getContentResolver(),
+ Settings.System.ACCELEROMETER_ROTATION,
+ mAccelerometerPref.isChecked() ? 1 : 0);
+ } else if (MAPS_COMPASS_PREF.equals(key)) {
+ try {
+ Context c = createPackageContext("com.google.android.apps.maps", 0);
+ c.getSharedPreferences("extra-features", MODE_WORLD_WRITEABLE)
+ .edit()
+ .putBoolean("compass", mShowMapsCompassPref.isChecked())
+ .commit();
+ } catch (NameNotFoundException e) {
+ Log.w(TAG, "Failed setting maps compass");
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ readAnimationPreference(0, mWindowAnimationsPref);
+ readAnimationPreference(1, mTransitionAnimationsPref);
+ readFontSizePreference(mFontSizePref);
+ readEndButtonPreference(mEndButtonPref);
+ updateToggles();
+ }
+}
diff --git a/apps/Term/AndroidManifest.xml b/apps/Term/AndroidManifest.xml
index 395d09c..8975fa4 100644
--- a/apps/Term/AndroidManifest.xml
+++ b/apps/Term/AndroidManifest.xml
@@ -1,7 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.term">
- <uses-permission android:name="android.permission.INTERNET"/>
<application android:icon="@drawable/app_terminal"
- android:label="Terminal Emulator">
+ android:label="@string/application_terminal">
<activity android:name="Term"
android:theme="@style/Theme"
android:launchMode="singleInstance"
@@ -11,5 +10,6 @@
<category android:name="android.intent.category.TEST" />
</intent-filter>
</activity>
+ <activity android:name="TermPreferences"/>
</application>
</manifest>
diff --git a/apps/Term/res/menu/main.xml b/apps/Term/res/menu/main.xml
new file mode 100644
index 0000000..5f6e9d8
--- /dev/null
+++ b/apps/Term/res/menu/main.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/menu_preferences"
+ android:title="@string/preferences" />
+ <item android:id="@+id/menu_reset"
+ android:title="@string/reset" />
+ <item android:id="@+id/menu_send_email"
+ android:title="@string/send_email" />
+ <item android:id="@+id/menu_special_keys"
+ android:title="@string/special_keys" />
+</menu>
diff --git a/apps/Term/res/values/arrays.xml b/apps/Term/res/values/arrays.xml
new file mode 100644
index 0000000..b4857a2
--- /dev/null
+++ b/apps/Term/res/values/arrays.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * 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.
+ -->
+
+<resources>
+ <string-array name="entries_fontsize_preference">
+ <item>4 x 8 pixels</item>
+ <item>6 pt</item>
+ <item>7 pt</item>
+ <item>8 pt</item>
+ <item>9 pt</item>
+ <item>10 pt</item>
+ <item>12 pt</item>
+ <item>14 pt</item>
+ <item>16 pt</item>
+ <item>20 pt</item>
+ </string-array>
+
+ <!-- Do not localize entryvalues -->
+ <string-array name="entryvalues_fontsize_preference">
+ <item>0</item>
+ <item>6</item>
+ <item>7</item>
+ <item>8</item>
+ <item>9</item>
+ <item>10</item>
+ <item>12</item>
+ <item>14</item>
+ <item>16</item>
+ <item>20</item>
+ </string-array>
+
+ <string-array name="entries_color_preference">
+ <item>Black text on white</item>
+ <item>White text on black</item>
+ <item>White text on blue</item>
+ </string-array>
+
+ <!-- Do not localize entryvalues -->
+ <string-array name="entryvalues_color_preference">
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ </string-array>
+
+ <string-array name="entries_controlkey_preference">
+ <item>Jog ball</item>
+ <item>\@ key</item>
+ <item>Left Alt key</item>
+ <item>Right Alt key</item>
+ </string-array>
+
+ <!-- Do not localize entryvalues -->
+ <string-array name="entryvalues_controlkey_preference">
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ <item>3</item>
+ </string-array>
+</resources>
diff --git a/apps/Term/res/values/strings.xml b/apps/Term/res/values/strings.xml
new file mode 100644
index 0000000..e3f8fcf
--- /dev/null
+++ b/apps/Term/res/values/strings.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * 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.
+-->
+<resources>
+ <string name="application_terminal">Terminal Emulator</string>
+ <string name="preferences">Preferences</string>
+ <string name="reset">Reset term</string>
+ <string name="send_email">Email to</string>
+ <string name="special_keys">Special keys</string>
+
+ <!-- Preference dialog -->
+ <string name="text_preferences">Text</string>
+
+ <string name="title_fontsize_preference">Font size</string>
+ <string name="summary_fontsize_preference">Choose character height in pixels.</string>
+ <string name="dialog_title_fontsize_preference">Font size</string>
+
+ <string name="title_color_preference">Colors</string>
+ <string name="summary_color_preference">Choose text color.</string>
+ <string name="dialog_title_color_preference">Text color</string>
+
+ <string name="keyboard_preferences">Keyboard</string>
+ <string name="title_controlkey_preference">Control key</string>
+ <string name="summary_controlkey_preference">Choose control key.</string>
+ <string name="dialog_title_controlkey_preference">Control key</string>
+
+ <string name="shell_preferences">Shell</string>
+ <string name="title_shell_preference">Command line</string>
+ <string name="summary_shell_preference">Specify the shell command line.</string>
+ <string name="dialog_title_shell_preference">Shell</string>
+
+ <string name="title_initialcommand_preference">Initial command</string>
+ <string name="summary_initialcommand_preference">Sent to the shell when it starts.</string>
+ <string name="dialog_title_initialcommand_preference">Initial Command</string>
+
+ <!-- Don't localize these default values -->
+ <string name="default_value_fontsize_preference">10</string>
+ <string name="default_value_color_preference">2</string>
+ <string name="default_value_controlkey_preference">0</string>
+ <string name="default_value_shell_preference">/system/bin/sh -</string>
+ <string name="default_value_initialcommand_preference">export PATH=/data/local/bin:$PATH</string>
+</resources>
diff --git a/apps/Term/res/xml/preferences.xml b/apps/Term/res/xml/preferences.xml
new file mode 100644
index 0000000..7792153
--- /dev/null
+++ b/apps/Term/res/xml/preferences.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <PreferenceCategory
+ android:title="@string/text_preferences">
+
+ <ListPreference
+ android:key="fontsize"
+ android:defaultValue="@string/default_value_fontsize_preference"
+ android:title="@string/title_fontsize_preference"
+ android:summary="@string/summary_fontsize_preference"
+ android:entries="@array/entries_fontsize_preference"
+ android:entryValues="@array/entryvalues_fontsize_preference"
+ android:dialogTitle="@string/dialog_title_fontsize_preference" />
+
+ <ListPreference
+ android:key="color"
+ android:defaultValue="@string/default_value_color_preference"
+ android:title="@string/title_color_preference"
+ android:summary="@string/summary_color_preference"
+ android:entries="@array/entries_color_preference"
+ android:entryValues="@array/entryvalues_color_preference"
+ android:dialogTitle="@string/dialog_title_color_preference" />
+
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:title="@string/keyboard_preferences">
+
+ <ListPreference
+ android:key="controlkey"
+ android:defaultValue="@string/default_value_controlkey_preference"
+ android:title="@string/title_controlkey_preference"
+ android:summary="@string/summary_controlkey_preference"
+ android:entries="@array/entries_controlkey_preference"
+ android:entryValues="@array/entryvalues_controlkey_preference"
+ android:dialogTitle="@string/dialog_title_controlkey_preference" />
+
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:title="@string/shell_preferences">
+
+ <EditTextPreference
+ android:key="shell"
+ android:defaultValue="@string/default_value_shell_preference"
+ android:title="@string/title_shell_preference"
+ android:summary="@string/summary_shell_preference"
+ android:dialogTitle="@string/dialog_title_shell_preference" />
+ <EditTextPreference
+ android:key="initialcommand"
+ android:defaultValue="@string/default_value_initialcommand_preference"
+ android:title="@string/title_initialcommand_preference"
+ android:summary="@string/summary_initialcommand_preference"
+ android:dialogTitle="@string/dialog_title_initialcommand_preference" />
+ </PreferenceCategory>
+</PreferenceScreen>
diff --git a/apps/Term/src/com/android/term/Term.java b/apps/Term/src/com/android/term/Term.java
index 61e85e9..b3bb7ee 100644
--- a/apps/Term/src/com/android/term/Term.java
+++ b/apps/Term/src/com/android/term/Term.java
@@ -20,16 +20,13 @@
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.ColorMatrix;
-import android.graphics.LightingColorFilter;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.PorterDuff;
@@ -50,14 +47,13 @@
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
-import android.view.SubMenu;
import android.view.View;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.util.Map;
+import java.util.ArrayList;
/**
* A terminal emulator activity.
@@ -66,12 +62,6 @@
public class Term extends Activity {
/**
- * Set to true to configure a test mode where the terminal emulator talks
- * directly to a test application, rather than to a shell.
- */
- public static final boolean TEST_MODE = false;
-
- /**
* Set to true to log each character received from the remote process to the
* android log, which makes it easier to debug some kinds of problems with
* emulating escape sequences and control codes.
@@ -99,6 +89,8 @@
*/
private FileDescriptor mTermFd;
+ private boolean mShellRunning;
+
/**
* Used to send data to the remote process.
*/
@@ -110,117 +102,262 @@
*/
private TermKeyListener mKeyListener;
- private boolean mWhiteOnBlue = true;
-
- private float mRotation;
-
/**
* The name of our emulator view in the view resource.
*/
private static final int EMULATOR_VIEW = R.id.emulatorView;
- // Menu IDs:
+ private int mFontSize = 9;
+ private int mColorId = 2;
+ private int mControlKeyId = 0;
- private static final int MENU_GROUP_NONE = Menu.FIRST;
- private static final int MENU_SCREEN_SIZE_ID = 0;
- private static final int MENU_SCREEN_SIZE_ITEM_ID = 1;
- private static final int MENU_SCREEN_SIZE_ITEM_COUNT = 10;
- private static final int MENU_SCREEN_SIZE_ITEM_ID_END =
- MENU_SCREEN_SIZE_ITEM_ID + MENU_SCREEN_SIZE_ITEM_COUNT;
-
- private static final int MENU_WHITE_ON_BLUE_ID =
- MENU_SCREEN_SIZE_ITEM_ID_END;
- private static final int MENU_RESET_TERMINAL_ID =
- MENU_SCREEN_SIZE_ITEM_ID_END + 1;
- private static final int MENU_EMAIL_TRANSCRIPT_ID =
- MENU_SCREEN_SIZE_ITEM_ID_END + 2;
-
- private static final int MENU_DOCUMENT_KEYS_ID =
- MENU_EMAIL_TRANSCRIPT_ID + 1;
-
- private static final String[] MENU_SCREEN_SIZE_LABELS = {
- "4 x 8", "6 pt", "7 pt", "8 pt", "9 pt", "10 pt", "12 pt",
- "14 pt", "16 pt", "20 pt"};
-
- private static final int[] TEXT_SIZE = {0, 6, 7, 8, 9, 10, 12, 14, 16, 20};
-
- private int mFontSelection = 3;
-
- private static final String FONT_SELECTION_KEY = "font selection";
- private static final String ROTATION_KEY = "rotation";
- private static final String WHITE_ON_BLUE_KEY = "whiteOnBlue";
+ private static final String FONTSIZE_KEY = "fontsize";
+ private static final String COLOR_KEY = "color";
+ private static final String CONTROLKEY_KEY = "controlkey";
+ private static final String SHELL_KEY = "shell";
+ private static final String INITIALCOMMAND_KEY = "initialcommand";
public static final int WHITE = 0xffffffff;
public static final int BLACK = 0xff000000;
public static final int BLUE = 0xff344ebd;
+ private static final int[][] COLOR_SCHEMES = {
+ {BLACK, WHITE}, {WHITE, BLACK}, {WHITE, BLUE}};
+
+ private static final int[] CONTROL_KEY_SCHEMES = {
+ KeyEvent.KEYCODE_DPAD_CENTER,
+ KeyEvent.KEYCODE_AT,
+ KeyEvent.KEYCODE_ALT_LEFT,
+ KeyEvent.KEYCODE_ALT_RIGHT
+ };
+ private static final String[] CONTROL_KEY_NAME = {
+ "Ball", "@", "Left-Alt", "Right-Alt"
+ };
+
+ private int mControlKeyCode;
+
+ private final static String DEFAULT_SHELL = "/system/bin/sh -";
+ private String mShell;
+
+ private final static String DEFAULT_INITIAL_COMMAND =
+ "export PATH=/data/local/bin:$PATH";
+ private String mInitialCommand;
+
private SharedPreferences mPrefs;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
Log.e(Term.LOG_TAG, "onCreate");
+ mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
+ mPrefs.registerOnSharedPreferenceChangeListener(
+ new SharedPreferences.OnSharedPreferenceChangeListener(){
+
+ public void onSharedPreferenceChanged(
+ SharedPreferences sharedPreferences, String key) {
+ readPrefs();
+ updatePrefs();
+ }});
+ readPrefs();
setContentView(R.layout.term_activity);
mEmulatorView = (EmulatorView) findViewById(EMULATOR_VIEW);
+ startListening();
+
+ mKeyListener = new TermKeyListener();
+
+ updatePrefs();
+ }
+
+ private void startListening() {
int[] processId = new int[1];
- if (TEST_MODE) {
- // This is a vt100 test suite.
- mTermFd = Exec.createSubprocess("/sbin/vttest", null, null);
- } else {
- // This is the standard Android shell.
- mTermFd = Exec.createSubprocess("/system/bin/sh", "-", null,
- processId);
- }
+ createSubprocess(processId);
+ mShellRunning = true;
final int procId = processId[0];
- final Term me = this;
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
- me.finish();
+ mShellRunning = false;
}
};
Runnable watchForDeath = new Runnable() {
public void run() {
- Log.e(Term.LOG_TAG, "waiting for: " + procId);
+ Log.i(Term.LOG_TAG, "waiting for: " + procId);
int result = Exec.waitFor(procId);
- Log.e(Term.LOG_TAG, "Subprocess exited: " + result);
- handler.sendEmptyMessage(0);
+ Log.i(Term.LOG_TAG, "Subprocess exited: " + result);
+ handler.sendEmptyMessage(result);
}
};
Thread watcher = new Thread(watchForDeath);
watcher.start();
- mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
- mFontSelection = mPrefs.getInt(FONT_SELECTION_KEY, mFontSelection);
- mWhiteOnBlue = mPrefs.getBoolean(WHITE_ON_BLUE_KEY, mWhiteOnBlue);
- mRotation = mPrefs.getFloat(ROTATION_KEY, mRotation);
-
mTermOut = new FileOutputStream(mTermFd);
mEmulatorView.initialize(mTermFd, mTermOut);
- mEmulatorView.setTextSize(TEXT_SIZE[mFontSelection]);
- mEmulatorView.setRotation(mRotation);
- setColors();
- mKeyListener = new TermKeyListener();
+ sendInitialCommand();
+ }
+
+ private void sendInitialCommand() {
+ String initialCommand = mInitialCommand;
+ if (initialCommand == null) {
+ initialCommand = DEFAULT_INITIAL_COMMAND;
+ }
+ if (initialCommand.length() > 0) {
+ write(initialCommand + '\r');
+ }
+ }
+
+ private void restart() {
+ startActivity(getIntent());
+ finish();
+ }
+
+ private void write(String data) {
+ try {
+ mTermOut.write(data.getBytes());
+ mTermOut.flush();
+ } catch (IOException e) {
+ // Ignore exception
+ // We don't really care if the receiver isn't listening.
+ // We just make a best effort to answer the query.
+ }
+ }
+
+ private void createSubprocess(int[] processId) {
+ String shell = mShell;
+ if (shell == null) {
+ shell = DEFAULT_SHELL;
+ }
+ ArrayList<String> args = parse(shell);
+ String arg0 = args.get(0);
+ String arg1 = null;
+ String arg2 = null;
+ if (args.size() >= 2) {
+ arg1 = args.get(1);
+ }
+ if (args.size() >= 3) {
+ arg2 = args.get(2);
+ }
+ mTermFd = Exec.createSubprocess(arg0, arg1, arg2, processId);
+ }
+
+ private ArrayList<String> parse(String cmd) {
+ final int PLAIN = 0;
+ final int WHITESPACE = 1;
+ final int INQUOTE = 2;
+ int state = WHITESPACE;
+ ArrayList<String> result = new ArrayList<String>();
+ int cmdLen = cmd.length();
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < cmdLen; i++) {
+ char c = cmd.charAt(i);
+ if (state == PLAIN) {
+ if (Character.isWhitespace(c)) {
+ result.add(builder.toString());
+ builder.delete(0,builder.length());
+ state = WHITESPACE;
+ } else if (c == '"') {
+ state = INQUOTE;
+ } else {
+ builder.append(c);
+ }
+ } else if (state == WHITESPACE) {
+ if (Character.isWhitespace(c)) {
+ // do nothing
+ } else if (c == '"') {
+ state = INQUOTE;
+ } else {
+ state = PLAIN;
+ builder.append(c);
+ }
+ } else if (state == INQUOTE) {
+ if (c == '\\') {
+ if (i + 1 < cmdLen) {
+ i += 1;
+ builder.append(cmd.charAt(i));
+ }
+ } else if (c == '"') {
+ state = PLAIN;
+ } else {
+ builder.append(c);
+ }
+ }
+ }
+ if (builder.length() > 0) {
+ result.add(builder.toString());
+ }
+ return result;
+ }
+
+ private void readPrefs() {
+ mFontSize = readIntPref(FONTSIZE_KEY, mFontSize, 20);
+ mColorId = readIntPref(COLOR_KEY, mColorId, COLOR_SCHEMES.length - 1);
+ mControlKeyId = readIntPref(CONTROLKEY_KEY, mControlKeyId,
+ CONTROL_KEY_SCHEMES.length - 1);
+ {
+ String newShell = readStringPref(SHELL_KEY, mShell);
+ if ((newShell == null) || ! newShell.equals(mShell)) {
+ if (mShell != null) {
+ Log.i(Term.LOG_TAG, "New shell set. Restarting.");
+ restart();
+ }
+ mShell = newShell;
+ }
+ }
+ {
+ String newInitialCommand = readStringPref(INITIALCOMMAND_KEY,
+ mInitialCommand);
+ if ((newInitialCommand == null)
+ || ! newInitialCommand.equals(mInitialCommand)) {
+ if (mInitialCommand != null) {
+ Log.i(Term.LOG_TAG, "New initial command set. Restarting.");
+ restart();
+ }
+ mInitialCommand = newInitialCommand;
+ }
+ }
+ }
+
+ private void updatePrefs() {
+ mEmulatorView.setTextSize(mFontSize);
+ setColors();
+ mControlKeyCode = CONTROL_KEY_SCHEMES[mControlKeyId];
+ }
+
+ private int readIntPref(String key, int defaultValue, int maxValue) {
+ int val;
+ try {
+ val = Integer.parseInt(
+ mPrefs.getString(key, Integer.toString(defaultValue)));
+ } catch (NumberFormatException e) {
+ val = defaultValue;
+ }
+ val = Math.max(0, Math.min(val, maxValue));
+ return val;
+ }
+
+ private String readStringPref(String key, String defaultValue) {
+ return mPrefs.getString(key, defaultValue);
}
@Override
public void onPause() {
SharedPreferences.Editor e = mPrefs.edit();
e.clear();
- e.putInt(FONT_SELECTION_KEY, mFontSelection);
- e.putBoolean(WHITE_ON_BLUE_KEY, mWhiteOnBlue);
- e.putFloat(ROTATION_KEY, mRotation);
+ e.putString(FONTSIZE_KEY, Integer.toString(mFontSize));
+ e.putString(COLOR_KEY, Integer.toString(mColorId));
+ e.putString(CONTROLKEY_KEY, Integer.toString(mControlKeyId));
+ e.putString(SHELL_KEY, mShell);
+ e.putString(INITIALCOMMAND_KEY, mInitialCommand);
e.commit();
super.onPause();
@@ -235,7 +372,9 @@
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (isSystemKey(keyCode, event)) {
+ if (handleControlKey(keyCode, true)) {
+ return true;
+ } else if (isSystemKey(keyCode, event)) {
// Don't intercept the system keys
return super.onKeyDown(keyCode, event);
} else if (handleDPad(keyCode, true)) {
@@ -257,7 +396,9 @@
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
- if (isSystemKey(keyCode, event)) {
+ if (handleControlKey(keyCode, false)) {
+ return true;
+ } else if (isSystemKey(keyCode, event)) {
// Don't intercept the system keys
return super.onKeyUp(keyCode, event);
} else if (handleDPad(keyCode, false)) {
@@ -268,44 +409,55 @@
return true;
}
+ private boolean handleControlKey(int keyCode, boolean down) {
+ if (keyCode == mControlKeyCode) {
+ mKeyListener.handleControlKey(down);
+ return true;
+ }
+ return false;
+ }
+
/**
* Handle dpad left-right-up-down events. Don't handle
* dpad-center, that's our control key.
* @param keyCode
* @param down
- * @return
*/
private boolean handleDPad(int keyCode, boolean down) {
if (keyCode < KeyEvent.KEYCODE_DPAD_UP ||
- keyCode > KeyEvent.KEYCODE_DPAD_RIGHT) {
+ keyCode > KeyEvent.KEYCODE_DPAD_CENTER) {
return false;
}
if (down) {
try {
- char code;
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_UP:
- code = 'A';
- break;
- case KeyEvent.KEYCODE_DPAD_DOWN:
- code = 'B';
- break;
- case KeyEvent.KEYCODE_DPAD_LEFT:
- code = 'D';
- break;
- default:
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- code = 'C';
- break;
- }
- mTermOut.write(27); // ESC
- if (mEmulatorView.getKeypadApplicationMode()) {
- mTermOut.write('O');
+ if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
+ mTermOut.write('\r');
} else {
- mTermOut.write('[');
+ char code;
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_UP:
+ code = 'A';
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ code = 'B';
+ break;
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ code = 'D';
+ break;
+ default:
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ code = 'C';
+ break;
+ }
+ mTermOut.write(27); // ESC
+ if (mEmulatorView.getKeypadApplicationMode()) {
+ mTermOut.write('O');
+ } else {
+ mTermOut.write('[');
+ }
+ mTermOut.write(code);
}
- mTermOut.write(code);
} catch (IOException e) {
// Ignore
}
@@ -319,82 +471,36 @@
@Override
public boolean onCreateOptionsMenu(Menu menu) {
- SubMenu screenSize = menu.addSubMenu(MENU_GROUP_NONE,
- MENU_SCREEN_SIZE_ID, 0, "Font Size");
- String[] labels = MENU_SCREEN_SIZE_LABELS;
- for (int i = 0; i < MENU_SCREEN_SIZE_ITEM_COUNT; i++) {
- MenuItem item = screenSize.add(i, MENU_SCREEN_SIZE_ITEM_ID + i, 0,
- labels[i]);
- item.setCheckable(true);
- }
- {
- MenuItem item = menu.add(MENU_WHITE_ON_BLUE_ID, MENU_WHITE_ON_BLUE_ID,
- 0, "Toggle White on Blue");
- }
- menu.add(MENU_RESET_TERMINAL_ID, MENU_RESET_TERMINAL_ID,
- 0, "Reset Terminal");
- menu.add(MENU_EMAIL_TRANSCRIPT_ID, MENU_EMAIL_TRANSCRIPT_ID,
- 0, "Email To...");
- menu.add(MENU_DOCUMENT_KEYS_ID, MENU_DOCUMENT_KEYS_ID,
- 0, "Special keys...");
- return true;
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- super.onPrepareOptionsMenu(menu);
- for (int i = 0; i < MENU_SCREEN_SIZE_ITEM_COUNT; i++) {
- menu.findItem(MENU_SCREEN_SIZE_ITEM_ID + i).setChecked(i == mFontSelection);
- }
+ getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
- if (id >= MENU_SCREEN_SIZE_ITEM_ID
- && id < MENU_SCREEN_SIZE_ITEM_ID_END) {
- doSetFontSize(id - MENU_SCREEN_SIZE_ITEM_ID);
- return true;
- } else if (id == MENU_WHITE_ON_BLUE_ID) {
- doWhiteOnBlue();
- } else if (id == MENU_RESET_TERMINAL_ID) {
+ if (id == R.id.menu_preferences) {
+ doPreferences();
+ } else if (id == R.id.menu_reset) {
doResetTerminal();
- } else if (id == MENU_EMAIL_TRANSCRIPT_ID) {
+ } else if (id == R.id.menu_send_email) {
doEmailTranscript();
- } else if (id == MENU_DOCUMENT_KEYS_ID) {
+ } else if (id == R.id.menu_special_keys) {
doDocumentKeys();
}
return super.onOptionsItemSelected(item);
}
- private void doWhiteOnBlue() {
- mWhiteOnBlue = ! mWhiteOnBlue;
- setColors();
- }
-
- private void doRotate90() {
- mRotation = mRotation != 0.0f ? 0.0f : 90.0f;
- mEmulatorView.setRotation(mRotation);
+ private void doPreferences() {
+ startActivity(new Intent(this, TermPreferences.class));
}
private void setColors() {
- if (mWhiteOnBlue) {
- mEmulatorView.setColors(WHITE, BLUE);
- } else {
- mEmulatorView.setColors(BLACK, WHITE);
- }
- }
-
- private void doSetFontSize(int i) {
- if (mFontSelection != i) {
- mFontSelection = i;
- mEmulatorView.setTextSize(TEXT_SIZE[i]);
- }
+ int[] scheme = COLOR_SCHEMES[mColorId];
+ mEmulatorView.setColors(scheme[0], scheme[1]);
}
private void doResetTerminal() {
- mEmulatorView.resetTerminal();
+ restart();
}
private void doEmailTranscript() {
@@ -411,15 +517,16 @@
}
private void doDocumentKeys() {
+ String controlKey = CONTROL_KEY_NAME[mControlKeyId];
new AlertDialog.Builder(this).
- setTitle("Press Jog Ball and Key").
- setMessage("Ball Space ==> Control-@ (NUL)\n"
- + "Ball A..Z ==> Control-A..Z\n"
- + "Ball 1 ==> Control-[ (ESC)\n"
- + "Ball 5 ==> Control-_\n"
- + "Ball . ==> Control-\\\n"
- + "Ball 0 ==> Control-]\n"
- + "Ball 6 ==> Control-^").
+ setTitle("Press " + controlKey + " and Key").
+ setMessage(controlKey + " Space ==> Control-@ (NUL)\n"
+ + controlKey + " A..Z ==> Control-A..Z\n"
+ + controlKey + " 1 ==> Control-[ (ESC)\n"
+ + controlKey + " 5 ==> Control-_\n"
+ + controlKey + " . ==> Control-\\\n"
+ + controlKey + " 0 ==> Control-]\n"
+ + controlKey + " 6 ==> Control-^").
show();
}
@@ -1857,6 +1964,10 @@
write(attributes);
}
+ /**
+ * Send data to the shell process
+ * @param data
+ */
private void write(byte[] data) {
try {
mTermOut.write(data);
@@ -2246,6 +2357,108 @@
}
/**
+ * A multi-thread-safe produce-consumer byte array.
+ * Only allows one producer and one consumer.
+ */
+
+class ByteQueue {
+ public ByteQueue(int size) {
+ mBuffer = new byte[size];
+ }
+
+ public int getBytesAvailable() {
+ synchronized(this) {
+ return mStoredBytes;
+ }
+ }
+
+ public int read(byte[] buffer, int offset, int length)
+ throws InterruptedException {
+ if (length + offset > buffer.length) {
+ throw
+ new IllegalArgumentException("length + offset > buffer.length");
+ }
+ if (length < 0) {
+ throw
+ new IllegalArgumentException("length < 0");
+
+ }
+ if (length == 0) {
+ return 0;
+ }
+ synchronized(this) {
+ while (mStoredBytes == 0) {
+ wait();
+ }
+ int totalRead = 0;
+ int bufferLength = mBuffer.length;
+ boolean wasFull = bufferLength == mStoredBytes;
+ while (length > 0 && mStoredBytes > 0) {
+ int oneRun = Math.min(bufferLength - mHead, mStoredBytes);
+ int bytesToCopy = Math.min(length, oneRun);
+ System.arraycopy(mBuffer, mHead, buffer, offset, bytesToCopy);
+ mHead += bytesToCopy;
+ if (mHead >= bufferLength) {
+ mHead = 0;
+ }
+ mStoredBytes -= bytesToCopy;
+ length -= bytesToCopy;
+ offset += bytesToCopy;
+ totalRead += bytesToCopy;
+ }
+ if (wasFull) {
+ notify();
+ }
+ return totalRead;
+ }
+ }
+
+ public void write(byte[] buffer, int offset, int length)
+ throws InterruptedException {
+ if (length + offset > buffer.length) {
+ throw
+ new IllegalArgumentException("length + offset > buffer.length");
+ }
+ if (length < 0) {
+ throw
+ new IllegalArgumentException("length < 0");
+
+ }
+ if (length == 0) {
+ return;
+ }
+ synchronized(this) {
+ int bufferLength = mBuffer.length;
+ boolean wasEmpty = mStoredBytes == 0;
+ while (length > 0) {
+ while(bufferLength == mStoredBytes) {
+ wait();
+ }
+ int tail = mHead + mStoredBytes;
+ int oneRun;
+ if (tail >= bufferLength) {
+ tail = tail - bufferLength;
+ oneRun = mHead - tail;
+ } else {
+ oneRun = bufferLength - tail;
+ }
+ int bytesToCopy = Math.min(oneRun, length);
+ System.arraycopy(buffer, offset, mBuffer, tail, bytesToCopy);
+ offset += bytesToCopy;
+ mStoredBytes += bytesToCopy;
+ length -= bytesToCopy;
+ }
+ if (wasEmpty) {
+ notify();
+ }
+ }
+ }
+
+ private byte[] mBuffer;
+ private int mHead;
+ private int mStoredBytes;
+}
+/**
* A view on a transcript and a terminal emulator. Displays the text of the
* transcript and the current cursor position of the terminal emulator.
*/
@@ -2340,6 +2553,9 @@
private FileOutputStream mTermOut;
+ private ByteQueue mByteQueue;
+ private final static int MAX_BYTES_PER_UPDATE = 4 * 1024;
+
/**
* Used to temporarily hold data received from the remote process. Allocated
* once and used permanently to minimize heap thrashing.
@@ -2347,25 +2563,16 @@
private byte[] mReceiveBuffer;
/**
- * Our private message id, which we use to check for new input from the
+ * Our private message id, which we use to receive new input from the
* remote process.
*/
private static final int UPDATE = 1;
/**
- * The period in milliseconds between updates.
+ * Thread that polls for input from the remote process
*/
- private static final int UPDATE_PERIOD_MS = 20;
- /**
- * The target time for our next update.
- */
- private long mNextTime;
-
- /**
- * Rotation amount for manual portrait/landscape rotation
- */
- private float mRotation;
+ private Thread mPollingThread;
private GestureDetector mGestureDetector;
private float mScrollRemainder;
@@ -2376,21 +2583,13 @@
private final Handler mHandler = new Handler() {
/**
* Handle the callback message. Call our enclosing class's update
- * method, and then reschedule another callback in the future. In this
- * way we implement a periodic callback.
+ * method.
*
* @param msg The callback message.
*/
public void handleMessage(Message msg) {
if (msg.what == UPDATE) {
update();
- msg = obtainMessage(UPDATE);
- long current = SystemClock.uptimeMillis();
- if (mNextTime < current) {
- mNextTime = current + UPDATE_PERIOD_MS;
- }
- sendMessageAtTime(msg, mNextTime);
- mNextTime += UPDATE_PERIOD_MS;
}
}
};
@@ -2465,18 +2664,17 @@
*
* @param termFd the file descriptor
* @param termOut the output stream for the pseudo-teletype
- * @param textSize the point size of the text font
*/
public void initialize(FileDescriptor termFd, FileOutputStream termOut) {
mTermOut = termOut;
mTermFd = termFd;
mTextSize = 10;
- mRotation = 0.0f;
mForeground = Term.WHITE;
mBackground = Term.BLACK;
updateText();
mTermIn = new FileInputStream(mTermFd);
mReceiveBuffer = new byte[4 * 1024];
+ mByteQueue = new ByteQueue(4 * 1024);
}
/**
@@ -2529,17 +2727,6 @@
updateText();
}
- /**
- * Set the rotation. Currently only 0 and 90 degrees are supported
- */
-
- public void setRotation(float angle) {
- mRotation = angle;
- if (mKnownSize) {
- updateSize(getWidth(), getHeight());
- }
- }
-
// Begin GestureDetector.OnGestureListener methods
public boolean onSingleTapUp(MotionEvent e) {
@@ -2625,21 +2812,31 @@
if (!mKnownSize) {
mKnownSize = true;
- // Set a timer so we're called back to check for input from the
+ // Set up a thread to read input from the
// pseudo-teletype:
- Message msg = mHandler.obtainMessage(UPDATE);
- mNextTime = SystemClock.uptimeMillis() + UPDATE_PERIOD_MS;
- mHandler.sendMessageAtTime(msg, mNextTime);
+
+ mPollingThread = new Thread(new Runnable() {
+
+ public void run() {
+ try {
+ while(true) {
+ int read = mTermIn.read(mBuffer);
+ mByteQueue.write(mBuffer, 0, read);
+ mHandler.sendMessage(
+ mHandler.obtainMessage(UPDATE));
+ }
+ } catch (IOException e) {
+ } catch (InterruptedException e) {
+ }
+ }
+ private byte[] mBuffer = new byte[4096];
+ });
+ mPollingThread.setName("Input reader");
+ mPollingThread.start();
}
}
private void updateSize(int w, int h) {
- if (mRotation != 0.0f) {
- int temp = w;
- w = h;
- h = temp;
- }
-
mColumns = w / mCharacterWidth;
mRows = h / mCharacterHeight;
@@ -2674,26 +2871,12 @@
* Look for new input from the ptty, send it to the terminal emulator.
*/
private void update() {
+ int bytesAvailable = mByteQueue.getBytesAvailable();
+ int bytesToRead = Math.min(bytesAvailable, mReceiveBuffer.length);
try {
- // To avoid starving user input, only process 20 KB
- // of input at once
- int processed = 0;
- while (processed < 20000) {
- int available =
- Math.min(mReceiveBuffer.length, mTermIn.available());
- if (available <= 0) {
- break;
- }
-
- int received = mTermIn.read(mReceiveBuffer, 0, available);
- if (received > 0) {
- append(mReceiveBuffer, 0, received);
- }
- processed += received;
- }
- } catch (IOException e) {
- // I/O exceptions break out of the input loop, but we don't
- // report them to the user.
+ int bytesRead = mByteQueue.read(mReceiveBuffer, 0, bytesToRead);
+ append(mReceiveBuffer, 0, bytesRead);
+ } catch (InterruptedException e) {
}
}
@@ -2701,14 +2884,6 @@
protected void onDraw(Canvas canvas) {
int w = getWidth();
int h = getHeight();
- if (mRotation != 0.0f) {
- canvas.save(Canvas.MATRIX_SAVE_FLAG);
- int pivot = Math.min(w, h) >> 1;
- canvas.rotate(mRotation, pivot, pivot);
- int temp = w;
- w = h;
- h = temp;
- }
canvas.drawRect(0, 0, w, h, mBackgroundPaint);
mVisibleColumns = w / mCharacterWidth;
float x = -mLeftColumn * mCharacterWidth;
@@ -2724,9 +2899,6 @@
mTranscriptScreen.drawText(i, canvas, x, y, mTextRenderer, cursorX);
y += mCharacterHeight;
}
- if (mRotation != 0.0f) {
- canvas.restore();
- }
}
private void ensureCursorVisible() {
@@ -2842,6 +3014,14 @@
public TermKeyListener() {
}
+ public void handleControlKey(boolean down) {
+ if (down) {
+ mControlKey.onPress();
+ } else {
+ mControlKey.onRelease();
+ }
+ }
+
/**
* Handle a keyDown event.
*
@@ -2862,10 +3042,6 @@
mCapKey.onPress();
break;
- case KeyEvent.KEYCODE_DPAD_CENTER:
- mControlKey.onPress();
- break;
-
case KeyEvent.KEYCODE_ENTER:
// Convert newlines into returns. The vt100 sends a
// '\r' when the 'Return' key is pressed, but our
@@ -2929,9 +3105,6 @@
case KeyEvent.KEYCODE_SHIFT_RIGHT:
mCapKey.onRelease();
break;
- case KeyEvent.KEYCODE_DPAD_CENTER:
- mControlKey.onRelease();
- break;
default:
// Ignore other keyUps
break;
diff --git a/apps/Term/src/com/android/term/TermPreferences.java b/apps/Term/src/com/android/term/TermPreferences.java
new file mode 100644
index 0000000..3102963
--- /dev/null
+++ b/apps/Term/src/com/android/term/TermPreferences.java
@@ -0,0 +1,32 @@
+/*
+ * 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.term;
+
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+
+public class TermPreferences extends PreferenceActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Load the preferences from an XML resource
+ addPreferencesFromResource(R.xml.preferences);
+ }
+
+}
diff --git a/build/Android.mk b/build/Android.mk
index a8a849d..cba96c6 100644
--- a/build/Android.mk
+++ b/build/Android.mk
@@ -4,7 +4,7 @@
# anywhere else, and the rules don't support. Aditionally, the depenencies on
# these files don't really matter, because they are all generated as part of
# building the docs. So for the dependency, we just use the
-# framework-timestamp file, which is the $@ of the droiddoc rule.
+# offline-sdk-timestamp file, which is the $@ of the droiddoc rule.
# We also need to depend on framework-res.apk, in order to pull the
# resource files out of there for aapt.
#
@@ -22,7 +22,7 @@
$(full_target): PRIVATE_CLASS_INTERMEDIATES_DIR := $(classes_dir)
$(full_target): PRIVATE_FRAMEWORK_RES_PACKAGE := $(framework_res_package)
-$(full_target): $(OUT_DOCS)/framework-timestamp $(framework_res_package)
+$(full_target): $(OUT_DOCS)/offline-sdk-timestamp $(framework_res_package)
@echo Compiling SDK Stubs: $@
$(hide) rm -rf $(PRIVATE_CLASS_INTERMEDIATES_DIR)
$(hide) mkdir -p $(PRIVATE_CLASS_INTERMEDIATES_DIR)
diff --git a/build/sdk.atree b/build/sdk.atree
index 113210e..2df42bc 100644
--- a/build/sdk.atree
+++ b/build/sdk.atree
@@ -30,39 +30,43 @@
development/tools/scripts/add-accounts-sdk tools/add-accounts.py
# the uper-jar file that apps link against
-out/target/common/obj/PACKAGING/android_jar_intermediates/android.jar android.jar
+out/target/common/obj/PACKAGING/android_jar_intermediates/android.jar platforms/${PLATFORM_NAME}/android.jar
-sdk/sdk-build.prop tools/lib/build.prop
+sdk/sdk-build.prop platforms/${PLATFORM_NAME}/build.prop
development/tools/scripts/plugin.prop tools/lib/plugin.prop
# the aidl precompiled include
-obj/framework.aidl tools/lib/framework.aidl
+obj/framework.aidl platforms/${PLATFORM_NAME}/framework.aidl
# sdk scripts
-development/tools/scripts/AndroidManifest.template tools/lib/AndroidManifest.template
-development/tools/scripts/AndroidManifest.alias.template tools/lib/AndroidManifest.alias.template
+development/tools/scripts/AndroidManifest.template platforms/${PLATFORM_NAME}/templates/AndroidManifest.template
+development/tools/scripts/AndroidManifest.alias.template platforms/${PLATFORM_NAME}/templates/AndroidManifest.alias.template
+development/tools/scripts/AndroidManifest.tests.template platforms/${PLATFORM_NAME}/templates/AndroidManifest.tests.template
+development/tools/scripts/iml.template platforms/${PLATFORM_NAME}/templates/iml.template
+development/tools/scripts/ipr.template platforms/${PLATFORM_NAME}/templates/ipr.template
+development/tools/scripts/iws.template platforms/${PLATFORM_NAME}/templates/iws.template
+development/tools/scripts/java_file.template platforms/${PLATFORM_NAME}/templates/java_file.template
+development/tools/scripts/java_tests_file.template platforms/${PLATFORM_NAME}/templates/java_tests_file.template
+development/tools/scripts/layout.template platforms/${PLATFORM_NAME}/templates/layout.template
+development/tools/scripts/strings.template platforms/${PLATFORM_NAME}/templates/strings.template
+development/tools/scripts/alias.template platforms/${PLATFORM_NAME}/templates/alias.template
development/tools/scripts/build.template tools/lib/build.template
development/tools/scripts/build.alias.template tools/lib/build.alias.template
development/tools/scripts/default.properties.template tools/lib/default.properties.template
-development/tools/scripts/iml.template tools/lib/iml.template
-development/tools/scripts/ipr.template tools/lib/ipr.template
-development/tools/scripts/iws.template tools/lib/iws.template
-development/tools/scripts/java_file.template tools/lib/java_file.template
-development/tools/scripts/layout.template tools/lib/layout.template
-development/tools/scripts/strings.template tools/lib/strings.template
-development/tools/scripts/alias.template tools/lib/alias.template
+development/tools/scripts/android_rules.xml tools/lib/android_rules.xml
+development/tools/scripts/alias_rules.xml tools/lib/alias_rules.xml
# emacs support
development/tools/scripts/android.el tools/lib/android.el
# samples
-development/samples/HelloActivity
-development/samples/Home
-development/samples/LunarLander
-development/samples/NotePad
-development/samples/ApiDemos
-development/samples/SkeletonApp
-development/samples/Snake
+development/samples/HelloActivity platforms/${PLATFORM_NAME}/samples/HelloActivity
+development/samples/Home platforms/${PLATFORM_NAME}/samples/Home
+development/samples/LunarLander platforms/${PLATFORM_NAME}/samples/LunarLander
+development/samples/NotePad platforms/${PLATFORM_NAME}/samples/NotePad
+development/samples/ApiDemos platforms/${PLATFORM_NAME}/samples/ApiDemos
+development/samples/SkeletonApp platforms/${PLATFORM_NAME}/samples/SkeletonApp
+development/samples/Snake platforms/${PLATFORM_NAME}/samples/Snake
# dx
bin/dx tools/dx
@@ -113,47 +117,53 @@
bin/activitycreator tools/activitycreator
framework/activitycreator.jar tools/lib/activitycreator.jar
+# sdkmanager
+bin/android tools/android
+framework/sdklib.jar tools/lib/sdklib.jar
+framework/sdkmanager.jar tools/lib/sdkmanager.jar
+
# emulator
bin/emulator tools/emulator
-system.img tools/lib/images/system.img
-ramdisk.img tools/lib/images/ramdisk.img
-userdata.img tools/lib/images/userdata.img
-userdata.img tools/lib/images/userdata.img
-development/emulator/prebuilt/android-arm/kernel-qemu tools/lib/images/kernel-qemu
+system.img platforms/${PLATFORM_NAME}/images/system.img
+ramdisk.img platforms/${PLATFORM_NAME}/images/ramdisk.img
+userdata.img platforms/${PLATFORM_NAME}/images/userdata.img
+prebuilt/android-arm/kernel/kernel-qemu platforms/${PLATFORM_NAME}/images/kernel-qemu
+external/qemu/android/vm/hardware-properties.ini tools/lib/hardware-properties.ini
# emulator skins
-development/emulator/skins/HVGA tools/lib/images/skins/HVGA
-development/emulator/skins/HVGA-L tools/lib/images/skins/HVGA-L
-development/emulator/skins/HVGA-P tools/lib/images/skins/HVGA-P
-development/emulator/skins/QVGA-L tools/lib/images/skins/QVGA-L
-development/emulator/skins/QVGA-P tools/lib/images/skins/QVGA-P
+development/emulator/skins/HVGA platforms/${PLATFORM_NAME}/skins/HVGA
+development/emulator/skins/HVGA-L platforms/${PLATFORM_NAME}/skins/HVGA-L
+development/emulator/skins/HVGA-P platforms/${PLATFORM_NAME}/skins/HVGA-P
+development/emulator/skins/QVGA-L platforms/${PLATFORM_NAME}/skins/QVGA-L
+development/emulator/skins/QVGA-P platforms/${PLATFORM_NAME}/skins/QVGA-P
-# NOTICE files are copied by config/Makefile
+# NOTICE files are copied by build/core/Makefile
# the readme
development/docs/SDK_RELEASE_NOTES RELEASE_NOTES.txt
# the docs
-docs/framework docs
+docs/offline-sdk docs
frameworks/base/docs/docs-redirect.html documentation.html
frameworks/base/docs/docs-samples-redirect.html docs/samples/index.html
# tools support
-docs/activity_actions.txt tools/lib/activity_actions.txt
-docs/broadcast_actions.txt tools/lib/broadcast_actions.txt
-docs/service_actions.txt tools/lib/service_actions.txt
-docs/categories.txt tools/lib/categories.txt
-docs/widgets.txt tools/lib/widgets.txt
-framework/layoutlib.jar tools/lib/layoutlib.jar
-frameworks/base/core/res tools/lib/res/default
-frameworks/base/data/fonts/fonts.xml tools/lib/fonts/default/fonts.xml
-frameworks/base/data/fonts/DroidSans.ttf tools/lib/fonts/default/DroidSans.ttf
-frameworks/base/data/fonts/DroidSans-Bold.ttf tools/lib/fonts/default/DroidSans-Bold.ttf
-frameworks/base/data/fonts/DroidSansFallback.ttf tools/lib/fonts/default/DroidSansFallback.ttf
-frameworks/base/data/fonts/DroidSansMono.ttf tools/lib/fonts/default/DroidSansMono.ttf
-frameworks/base/data/fonts/DroidSerif-Bold.ttf tools/lib/fonts/default/DroidSerif-Bold.ttf
-frameworks/base/data/fonts/DroidSerif-BoldItalic.ttf tools/lib/fonts/default/DroidSerif-BoldItalic.ttf
-frameworks/base/data/fonts/DroidSerif-Italic.ttf tools/lib/fonts/default/DroidSerif-Italic.ttf
-frameworks/base/data/fonts/DroidSerif-Regular.ttf tools/lib/fonts/default/DroidSerif-Regular.ttf
+docs/activity_actions.txt platforms/${PLATFORM_NAME}/data/activity_actions.txt
+docs/broadcast_actions.txt platforms/${PLATFORM_NAME}/data/broadcast_actions.txt
+docs/service_actions.txt platforms/${PLATFORM_NAME}/data/service_actions.txt
+docs/categories.txt platforms/${PLATFORM_NAME}/data/categories.txt
+docs/widgets.txt platforms/${PLATFORM_NAME}/data/widgets.txt
+framework/layoutlib.jar platforms/${PLATFORM_NAME}/data/layoutlib.jar
+frameworks/base/core/res/res platforms/${PLATFORM_NAME}/data/res
+frameworks/base/data/fonts/fonts.xml platforms/${PLATFORM_NAME}/data/fonts/fonts.xml
+frameworks/base/data/fonts/DroidSans.ttf platforms/${PLATFORM_NAME}/data/fonts/DroidSans.ttf
+frameworks/base/data/fonts/DroidSans-Bold.ttf platforms/${PLATFORM_NAME}/data/fonts/DroidSans-Bold.ttf
+frameworks/base/data/fonts/DroidSansFallback.ttf platforms/${PLATFORM_NAME}/data/fonts/DroidSansFallback.ttf
+frameworks/base/data/fonts/DroidSansMono.ttf platforms/${PLATFORM_NAME}/data/fonts/DroidSansMono.ttf
+frameworks/base/data/fonts/DroidSerif-Bold.ttf platforms/${PLATFORM_NAME}/data/fonts/DroidSerif-Bold.ttf
+frameworks/base/data/fonts/DroidSerif-BoldItalic.ttf platforms/${PLATFORM_NAME}/data/fonts/DroidSerif-BoldItalic.ttf
+frameworks/base/data/fonts/DroidSerif-Italic.ttf platforms/${PLATFORM_NAME}/data/fonts/DroidSerif-Italic.ttf
+frameworks/base/data/fonts/DroidSerif-Regular.ttf platforms/${PLATFORM_NAME}/data/fonts/DroidSerif-Regular.ttf
-
+# empty add-on folder with just a readme
+development/tools/scripts/README_add-ons.txt add-ons/README.txt
diff --git a/build/tools/make_windows_sdk.sh b/build/tools/make_windows_sdk.sh
new file mode 100755
index 0000000..f49165c
--- /dev/null
+++ b/build/tools/make_windows_sdk.sh
@@ -0,0 +1,129 @@
+#!/bin/bash
+# Quick semi-auto file to build Windows SDK tools.
+#
+# Limitations:
+# - Expects the emulator has been built first, will pick it up from prebuilt.
+# - Run in Cygwin
+# - Needs Cygwin package zip
+# - Expects to have one of the existing SDK (Darwin or Linux) to build the Windows one
+
+set -e # Fail this script as soon as a command fails -- fail early, fail fast
+
+SDK_ZIP="$1"
+DIST_DIR="$2"
+
+function die() {
+ echo "Error:" $*
+ echo "Aborting"
+ exit 1
+}
+
+function check() {
+ [ -f "$SDK_ZIP" ] || die "Pass the path of an existing Linux/Darwin SDK .zip as first parameter"
+ [ -d "$DIST_DIR" ] || die "Pass the output directory as second parameter"
+
+ # Use the BUILD_ID as SDK_NUMBER if defined, otherwise try to get it from the
+ # provided zip filename.
+ if [ -f config/build_id.make ]; then
+ BUILD_ID=`cat config/build_id.make | sed -n '/BUILD_ID=/s/^[^=]\+=\(.*\)$/\1/p'`
+ [ -n "$BUILD_ID" ] && SDK_NUMBER="$BUILD_ID"
+ fi
+ if [ -z "$SDK_NUMBER" ]; then
+ # Look for a pattern like "anything_sdknumber.extension"
+ # The pattern is now "any-thing_sdknumber_anything-else.extension"
+ #
+ # The bottom line is that the SDK number is whatever is enclosed by
+ # the LAST couple of underscores. You can have underscores *before* the
+ # SDK number if you want, but not after, e.g these are valid:
+ # android_sdk_4242_platform.zip or blah_42_.zip
+ #
+ # SDK_NUMBER will be empty if nothing matched.
+ filename=`basename "$SDK_ZIP"`
+ SDK_NUMBER=`echo $filename | sed -n 's/^.*_\([^_./]\+\)_[^_.]*\..*$/\1/p'`
+ fi
+
+ [ -n "$SDK_NUMBER" ] || die "Failed to extract the SDK number from $SDK_ZIP. Check its format."
+
+ [ $OSTYPE == "cygwin" ] || die "This expects to run under Cygwin"
+ [ -e `which zip` ] || die "Please install 'zip' package in Cygwin"
+ [ -f "build/envsetup.sh" ] || die "Please run this from the 'android' directory"
+
+ echo "Using SDK ${SDK_NUMBER}"
+}
+
+function build() {
+
+ echo
+ echo "Building..."
+ [ -n "$MAKE_OPT" ] && echo "Make options: $MAKE_OPT"
+ . build/envsetup.sh
+ make -j 4 emulator || die "Build failed"
+ # Disable parallel build: it generates "permission denied" issues when
+ # multiple "ar.exe" are running in parallel.
+ make prebuilt adb fastboot aidl aapt dexdump dmtracedump mksdcard sqlite3 || die "Build failed"
+}
+
+function package() {
+ echo
+ echo "Packaging..."
+ DEST_NAME="android-sdk_${SDK_NUMBER}_windows"
+ DEST="$DIST_DIR/$DEST_NAME"
+ DEST_NAME_ZIP="${DEST_NAME}.zip"
+
+ # Unzip current linux/mac SDK and rename using the windows name
+ [ -e "$DEST" ] && rm -rfv "$DEST" # cleanup dest first if exists
+ UNZIPPED=`basename "$SDK_ZIP"`
+ UNZIPPED="$DIST_DIR/${UNZIPPED/.zip/}"
+ [ -e "$UNZIPPED" ] && rm -rfv "$UNZIPPED" # cleanup unzip dir (if exists)
+ unzip "$SDK_ZIP" -d "$DIST_DIR"
+ mv -v "$UNZIPPED" "$DEST"
+
+ # USB Driver is not in tools
+ mkdir -pv $DEST/usb_driver
+ cp -rv development/host/windows/prebuilt/usb/driver/* $DEST/usb_driver
+
+ # Remove obsolete stuff from tools
+ TOOLS="$DEST/tools"
+ LIB="$DEST/tools/lib"
+ rm -v "$TOOLS"/{aapt,aidl,adb,emulator,traceview,draw9patch,hierarchyviewer,dx,dexdump,apkbuilder,ddms,dmtracedump,mksdcard,sqlite3,activitycreator,android}
+ rm -v --force "$LIB"/*.so "$LIB"/*.jnilib
+
+ # Copy all the new stuff in tools
+ cp -v out/host/windows-x86/bin/*.{exe,dll} "$TOOLS"
+ cp -v prebuilt/windows/swt/*.{jar,dll} "$LIB"
+ # Do we want the emulator NOTICE in the tools dir? Cf http://b/930608.
+ # If yes, uncomment the following line:
+ # cp -v external/qemu/NOTICE "$TOOLS"/emulator_NOTICE.txt
+
+
+ # We currently need libz from MinGW for aapt
+ cp -v /cygdrive/c/cygwin/bin/mgwz.dll "$TOOLS"
+
+ # Update a bunch of bat files
+ cp -v dalvik/dx/etc/dx.bat "$TOOLS"
+ cp -v development/tools/apkbuilder/etc/apkbuilder.bat "$TOOLS"
+ cp -v development/tools/ddms/app/etc/ddms.bat "$TOOLS"
+ cp -v development/tools/traceview/etc/traceview.bat "$TOOLS"
+ cp -v development/tools/hierarchyviewer/etc/hierarchyviewer.bat "$TOOLS"
+ cp -v development/tools/draw9patch/etc/draw9patch.bat "$TOOLS"
+ cp -v development/tools/activitycreator/etc/activitycreator.bat "$TOOLS"
+ cp -v development/tools/sdkmanager/app/etc/android.bat "$TOOLS"
+
+ # Fix EOL chars to make window users happy - fix all files at the top level only
+ find "$DIST_DIR" -maxdepth 1 -type f -print | xargs unix2dos -D
+
+ # Done.. Zip it
+ pushd "$DIST_DIR" > /dev/null
+ [ -e "$DEST_NAME_ZIP" ] && rm -rfv "$DEST_NAME_ZIP"
+ zip -9r "$DEST_NAME_ZIP" "$DEST_NAME" && rm -rfv "$DEST_NAME"
+ popd > /dev/null
+ echo "Done"
+ echo
+ echo "Resulting SDK is in $DIST_DIR/$DEST_NAME_ZIP"
+}
+
+check
+build
+package
+
+echo "Done"
diff --git a/cmds/monkey/src/com/android/commands/monkey/Monkey.java b/cmds/monkey/src/com/android/commands/monkey/Monkey.java
index 5a8080c..f6ab19d 100644
--- a/cmds/monkey/src/com/android/commands/monkey/Monkey.java
+++ b/cmds/monkey/src/com/android/commands/monkey/Monkey.java
@@ -28,13 +28,8 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemClock;
import android.server.data.CrashData;
-import android.view.Display;
import android.view.IWindowManager;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.WindowManagerImpl;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
@@ -43,12 +38,10 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import java.util.Random;
/**
* Application that injects random key events and other actions into the system.
@@ -62,117 +55,6 @@
*/
private final static int DEBUG_ALLOW_ANY_STARTS = 0;
private final static int DEBUG_ALLOW_ANY_RESTARTS = 0;
-
- /** Key events that move around the UI. */
- private final int[] NAV_KEYS = {
- KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN,
- KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_RIGHT,
- };
- /**
- * Key events that perform major navigation options (so shouldn't be sent
- * as much).
- */
- private final int[] MAJOR_NAV_KEYS = {
- KeyEvent.KEYCODE_MENU, /*KeyEvent.KEYCODE_SOFT_RIGHT,*/
- KeyEvent.KEYCODE_DPAD_CENTER,
- };
- /** Key events that perform system operations. */
- private final int[] SYS_KEYS = {
- KeyEvent.KEYCODE_HOME, KeyEvent.KEYCODE_BACK,
- KeyEvent.KEYCODE_CALL, KeyEvent.KEYCODE_ENDCALL,
- KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_VOLUME_DOWN,
- };
- /** Nice names for all key events. */
- private final String[] KEY_NAMES = {
- "KEYCODE_UNKNOWN",
- "KEYCODE_MENU",
- "KEYCODE_SOFT_RIGHT",
- "KEYCODE_HOME",
- "KEYCODE_BACK",
- "KEYCODE_CALL",
- "KEYCODE_ENDCALL",
- "KEYCODE_0",
- "KEYCODE_1",
- "KEYCODE_2",
- "KEYCODE_3",
- "KEYCODE_4",
- "KEYCODE_5",
- "KEYCODE_6",
- "KEYCODE_7",
- "KEYCODE_8",
- "KEYCODE_9",
- "KEYCODE_STAR",
- "KEYCODE_POUND",
- "KEYCODE_DPAD_UP",
- "KEYCODE_DPAD_DOWN",
- "KEYCODE_DPAD_LEFT",
- "KEYCODE_DPAD_RIGHT",
- "KEYCODE_DPAD_CENTER",
- "KEYCODE_VOLUME_UP",
- "KEYCODE_VOLUME_DOWN",
- "KEYCODE_POWER",
- "KEYCODE_CAMERA",
- "KEYCODE_CLEAR",
- "KEYCODE_A",
- "KEYCODE_B",
- "KEYCODE_C",
- "KEYCODE_D",
- "KEYCODE_E",
- "KEYCODE_F",
- "KEYCODE_G",
- "KEYCODE_H",
- "KEYCODE_I",
- "KEYCODE_J",
- "KEYCODE_K",
- "KEYCODE_L",
- "KEYCODE_M",
- "KEYCODE_N",
- "KEYCODE_O",
- "KEYCODE_P",
- "KEYCODE_Q",
- "KEYCODE_R",
- "KEYCODE_S",
- "KEYCODE_T",
- "KEYCODE_U",
- "KEYCODE_V",
- "KEYCODE_W",
- "KEYCODE_X",
- "KEYCODE_Y",
- "KEYCODE_Z",
- "KEYCODE_COMMA",
- "KEYCODE_PERIOD",
- "KEYCODE_ALT_LEFT",
- "KEYCODE_ALT_RIGHT",
- "KEYCODE_SHIFT_LEFT",
- "KEYCODE_SHIFT_RIGHT",
- "KEYCODE_TAB",
- "KEYCODE_SPACE",
- "KEYCODE_SYM",
- "KEYCODE_EXPLORER",
- "KEYCODE_ENVELOPE",
- "KEYCODE_ENTER",
- "KEYCODE_DEL",
- "KEYCODE_GRAVE",
- "KEYCODE_MINUS",
- "KEYCODE_EQUALS",
- "KEYCODE_LEFT_BRACKET",
- "KEYCODE_RIGHT_BRACKET",
- "KEYCODE_BACKSLASH",
- "KEYCODE_SEMICOLON",
- "KEYCODE_APOSTROPHE",
- "KEYCODE_SLASH",
- "KEYCODE_AT",
- "KEYCODE_NUM",
- "KEYCODE_HEADSETHOOK",
- "KEYCODE_FOCUS",
- "KEYCODE_PLUS",
- "KEYCODE_MENU",
- "KEYCODE_NOTIFICATION",
- "KEYCODE_SEARCH",
-
- "TAG_LAST_KEYCODE" // EOL. used to keep the lists in sync
- };
-
private IActivityManager mAm;
private IWindowManager mWm;
private IPackageManager mPm;
@@ -238,25 +120,16 @@
long mDroppedKeyEvents = 0;
long mDroppedPointerEvents = 0;
long mDroppedTrackballEvents = 0;
-
- /** percentages for each type of event. These will be remapped to working
- * values after we read any optional values.
- **/
- public static final int FACTOR_TOUCH = 0;
- public static final int FACTOR_MOTION = 1;
- public static final int FACTOR_TRACKBALL = 2;
- public static final int FACTOR_NAV = 3;
- public static final int FACTOR_MAJORNAV = 4;
- public static final int FACTOR_SYSOPS = 5;
- public static final int FACTOR_APPSWITCH = 6;
- public static final int FACTOR_ANYTHING = 7;
-
- public static final int FACTORZ_COUNT = 8; // should be last+1
-
- float[] mFactors = new float[FACTORZ_COUNT];
+ long mDroppedFlipEvents = 0;
+
+ /** a filename to the script (if any) **/
+ private String mScriptFileName = null;
private static final File TOMBSTONES_PATH = new File("/data/tombstones");
private HashSet<String> mTombstones = null;
+
+ float[] mFactors = new float[MonkeySourceRandom.FACTORZ_COUNT];
+ MonkeyEventSource mEventSource;
/**
* Monitor operations happening in the system.
@@ -440,21 +313,15 @@
mSeed = 0;
mThrottle = 0;
- // default values for random distributions
- // note, these are straight percentages, to match user input (cmd line args)
- // but they will be converted to 0..1 values before the main loop runs.
- mFactors[FACTOR_TOUCH] = 15.0f;
- mFactors[FACTOR_MOTION] = 10.0f;
- mFactors[FACTOR_TRACKBALL] = 15.0f;
- mFactors[FACTOR_NAV] = 25.0f;
- mFactors[FACTOR_MAJORNAV] = 15.0f;
- mFactors[FACTOR_SYSOPS] = 2.0f;
- mFactors[FACTOR_APPSWITCH] = 2.0f;
- mFactors[FACTOR_ANYTHING] = 16.0f;
-
// prepare for command-line processing
mArgs = args;
mNextArg = 0;
+
+ //set a positive value, indicating none of the factors is provided yet
+ for (int i = 0; i < MonkeySourceRandom.FACTORZ_COUNT; i++) {
+ mFactors[i] = 1.0f;
+ }
+
if (!processOptions()) {
return -1;
}
@@ -493,16 +360,40 @@
return -4;
}
- if (!adjustEventFactors()) {
- return -5;
+ if (mScriptFileName != null) {
+ // script mode, ignore other options
+ mEventSource = new MonkeySourceScript(mScriptFileName);
+ mEventSource.setVerbose(mVerbose);
+ } else {
+ // random source by default
+ if (mVerbose >= 2) { // check seeding performance
+ System.out.println("// Seeded: " + mSeed);
+ }
+ mEventSource = new MonkeySourceRandom(mSeed, mMainApps);
+ mEventSource.setVerbose(mVerbose);
+ //set any of the factors that has been set
+ for (int i = 0; i < MonkeySourceRandom.FACTORZ_COUNT; i++) {
+ if (mFactors[i] <= 0.0f) {
+ ((MonkeySourceRandom) mEventSource).setFactors(i, mFactors[i]);
+ }
+ }
+
+ //in random mode, we start with a random activity
+ ((MonkeySourceRandom) mEventSource).generateActivity();
}
- // Java's Random doesn't scramble well at all on seeding, so we'll use
- // the better random source here.
- SecureRandom random = new SecureRandom();
- random.setSeed((mSeed == 0) ? -1 : mSeed);
- if (mVerbose >= 2) { // check seeding performance
- System.out.println("// Seeded: " + mSeed + " and pulling: " + random.nextFloat());
+ //validate source generator
+ if (!mEventSource.validate()) {
+ return -5;
+ }
+
+ if (mScriptFileName != null) {
+ // in random mode, count is the number of single events
+ // while in script mode, count is the number of repetition
+ // for a sequence of events, so we need do multiply the length of
+ // that sequence
+ mCount = mCount * ((MonkeySourceScript) mEventSource)
+ .getOneRoundEventCount();
}
// If we're profiling, do it immediately before/after the main monkey loop
@@ -510,7 +401,7 @@
signalPersistentProcesses();
}
- int crashedAtCycle = runMonkeyCycles(random);
+ int crashedAtCycle = runMonkeyCycles();
synchronized (this) {
if (mRequestAnrTraces) {
@@ -536,7 +427,7 @@
// just in case this was latent (after mCount cycles), make sure
// we report it
if (crashedAtCycle >= mCount) {
- crashedAtCycle = mCount -1;
+ crashedAtCycle = mCount - 1;
}
}
@@ -547,10 +438,12 @@
System.out.print(" pointers=");
System.out.print(mDroppedPointerEvents);
System.out.print(" trackballs=");
- System.out.println(mDroppedTrackballEvents);
+ System.out.print(mDroppedTrackballEvents);
+ System.out.print(" flips=");
+ System.out.println(mDroppedFlipEvents);
}
- if (crashedAtCycle < mCount) {
+ if (crashedAtCycle < mCount - 1) {
System.err.println("** System appears to have crashed at event "
+ crashedAtCycle + " of " + mCount + " using seed " + mSeed);
return crashedAtCycle;
@@ -576,7 +469,7 @@
try {
String opt;
- while ((opt=nextOption()) != null) {
+ while ((opt = nextOption()) != null) {
if (opt.equals("-s")) {
mSeed = nextOptionLong("Seed");
} else if (opt.equals("-p")) {
@@ -598,27 +491,37 @@
} else if (opt.equals("--hprof")) {
mGenerateHprof = true;
} else if (opt.equals("--pct-touch")) {
- mFactors[FACTOR_TOUCH] = -nextOptionLong("touch events percentage");
+ mFactors[MonkeySourceRandom.FACTOR_TOUCH] =
+ -nextOptionLong("touch events percentage");
} else if (opt.equals("--pct-motion")) {
- mFactors[FACTOR_MOTION] = -nextOptionLong("motion events percentage");
+ mFactors[MonkeySourceRandom.FACTOR_MOTION] =
+ -nextOptionLong("motion events percentage");
} else if (opt.equals("--pct-trackball")) {
- mFactors[FACTOR_TRACKBALL] = -nextOptionLong("trackball events percentage");
- } else if (opt.equals("--pct-syskeys")) {
- mFactors[FACTOR_SYSOPS] = -nextOptionLong("system key events percentage");
+ mFactors[MonkeySourceRandom.FACTOR_TRACKBALL] =
+ -nextOptionLong("trackball events percentage");
} else if (opt.equals("--pct-nav")) {
- mFactors[FACTOR_NAV] = -nextOptionLong("nav events percentage");
+ mFactors[MonkeySourceRandom.FACTOR_NAV] =
+ -nextOptionLong("nav events percentage");
} else if (opt.equals("--pct-majornav")) {
- mFactors[FACTOR_MAJORNAV] = -nextOptionLong("major nav events percentage");
+ mFactors[MonkeySourceRandom.FACTOR_MAJORNAV] =
+ -nextOptionLong("major nav events percentage");
} else if (opt.equals("--pct-appswitch")) {
- mFactors[FACTOR_APPSWITCH] = -nextOptionLong("app switch events percentage");
+ mFactors[MonkeySourceRandom.FACTOR_APPSWITCH] =
+ -nextOptionLong("app switch events percentage");
+ } else if (opt.equals("--pct-flip")) {
+ mFactors[MonkeySourceRandom.FACTOR_FLIP] =
+ -nextOptionLong("keyboard flip percentage");
} else if (opt.equals("--pct-anyevent")) {
- mFactors[FACTOR_ANYTHING] = -nextOptionLong("any events percentage");
+ mFactors[MonkeySourceRandom.FACTOR_ANYTHING] =
+ -nextOptionLong("any events percentage");
} else if (opt.equals("--throttle")) {
- mThrottle = nextOptionLong("delay (in milliseconds) to wait between events");
+ mThrottle = nextOptionLong("delay (in milliseconds) to wait between events");
} else if (opt.equals("--wait-dbg")) {
// do nothing - it's caught at the very start of run()
} else if (opt.equals("--dbg-no-events")) {
mSendNoEvents = true;
+ } else if (opt.equals("-f")) {
+ mScriptFileName = nextOptionData();
} else if (opt.equals("-h")) {
showUsage();
return false;
@@ -648,10 +551,10 @@
showUsage();
return false;
}
-
+
return true;
}
-
+
/**
* Check for any internal configuration (primarily build-time) errors.
*
@@ -659,13 +562,13 @@
*/
private boolean checkInternalConfiguration() {
// Check KEYCODE name array, make sure it's up to date.
-
+
String lastKeyName = null;
try {
- lastKeyName = KEY_NAMES[KeyEvent.MAX_KEYCODE+1];
+ lastKeyName = MonkeySourceRandom.getLastKeyName();
} catch (RuntimeException e) {
}
- if (! "TAG_LAST_KEYCODE".equals(lastKeyName)) {
+ if (!"TAG_LAST_KEYCODE".equals(lastKeyName)) {
System.err.println("** Error: Key names array malformed (internal error).");
return false;
}
@@ -685,8 +588,7 @@
return false;
}
- mWm = IWindowManager.Stub.asInterface(
- ServiceManager.getService("window"));
+ mWm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
if (mWm == null) {
System.err.println("** Error: Unable to connect to window manager; is the system running?");
return false;
@@ -697,7 +599,7 @@
System.err.println("** Error: Unable to connect to package manager; is the system running?");
return false;
}
-
+
try {
mAm.setActivityWatcher(new ActivityWatcher());
} catch (RemoteException e) {
@@ -707,7 +609,7 @@
return true;
}
-
+
/**
* Using the restrictions provided (categories & packages), generate a list of activities
* that we can actually switch to.
@@ -717,7 +619,7 @@
private boolean getMainApps() {
try {
final int N = mMainCategories.size();
- for (int i=0; i<N; i++) {
+ for (int i = 0; i< N; i++) {
Intent intent = new Intent(Intent.ACTION_MAIN);
String category = mMainCategories.get(i);
if (category.length() > 0) {
@@ -732,7 +634,7 @@
System.out.println("// Selecting main activities from category " + category);
}
final int NA = mainApps.size();
- for (int a=0; a<NA; a++) {
+ for (int a = 0; a < NA; a++) {
ResolveInfo r = mainApps.get(a);
if (mValidPackages.size() == 0 ||
mValidPackages.contains(r.activityInfo.applicationInfo.packageName)) {
@@ -769,87 +671,20 @@
return true;
}
-
- /**
- * Adjust the percentages (after applying user values) and then normalize to a 0..1 scale.
- */
- private boolean adjustEventFactors() {
- // go through all values and compute totals for user & default values
- float userSum = 0.0f;
- float defaultSum = 0.0f;
- int defaultCount = 0;
- for (int i = 0; i < FACTORZ_COUNT; ++i) {
- if (mFactors[i] <= 0.0f) { // user values are zero or negative
- userSum -= mFactors[i];
- } else {
- defaultSum += mFactors[i];
- ++defaultCount;
- }
- }
-
- // if the user request was > 100%, reject it
- if (userSum > 100.0f) {
- System.err.println("** Event weights > 100%");
- showUsage();
- return false;
- }
-
- // if the user specified all of the weights, then they need to be 100%
- if (defaultCount == 0 && (userSum < 99.9f || userSum > 100.1f)) {
- System.err.println("** Event weights != 100%");
- showUsage();
- return false;
- }
-
- // compute the adjustment necessary
- float defaultsTarget = (100.0f - userSum);
- float defaultsAdjustment = defaultsTarget / defaultSum;
-
- // fix all values, by adjusting defaults, or flipping user values back to >0
- for (int i = 0; i < FACTORZ_COUNT; ++i) {
- if (mFactors[i] <= 0.0f) { // user values are zero or negative
- mFactors[i] = -mFactors[i];
- } else {
- mFactors[i] *= defaultsAdjustment;
- }
- }
-
- // if verbose, show factors
- if (mVerbose > 0) {
- System.out.println("// Event percentages:");
- for (int i = 0; i < FACTORZ_COUNT; ++i) {
- System.out.println("// " + i + ": " + mFactors[i] + "%");
- }
- }
-
- // finally, normalize and convert to running sum
- float sum = 0.0f;
- for (int i = 0; i < FACTORZ_COUNT; ++i) {
- sum += mFactors[i] / 100.0f;
- mFactors[i] = sum;
- }
-
- return true;
- }
-
+
/**
* Run mCount cycles and see if we hit any crashers.
*
- * TODO: Meta state on keys
+ * TODO: Meta state on keys
*
- * @param random The random source to use
- * @return Returns the last cycle which executed. If the value == mCount, no errors detected.
+ * @return Returns the last cycle which executed. If the value == mCount, no errors detected.
*/
- private int runMonkeyCycles(Random random) {
+ private int runMonkeyCycles() {
int i = 0;
int lastKey = 0;
boolean systemCrashed = false;
- if (!startRandomActivity(random)) {
- systemCrashed = true;
- }
-
while (!systemCrashed && i < mCount) {
synchronized (this) {
if (mRequestAnrTraces) {
@@ -873,14 +708,14 @@
return i;
}
}
-
+
try {
- Thread.sleep(mThrottle);
+ Thread.sleep(mThrottle);
} catch (InterruptedException e1) {
- System.out.println("** Monkey interrupted in sleep.");
- return i;
+ System.out.println("** Monkey interrupted in sleep.");
+ return i;
}
-
+
// In this debugging mode, we never send any events. This is primarily
// here so you can manually test the package or category limits, while manually
// exercising the system.
@@ -889,221 +724,35 @@
continue;
}
- if ((mVerbose > 0) && (i%100) == 0 && i != 0 && lastKey == 0) {
+ if ((mVerbose > 0) && (i % 100) == 0 && i != 0 && lastKey == 0) {
System.out.println(" // Sending event #" + i);
}
- // if the last event was a keydown, then this event is a key-up
- if (lastKey != 0) {
- if (mVerbose > 1) {
- try {
- System.out.println(":SendKey (ACTION_UP):" + lastKey + " // " + KEY_NAMES[lastKey]);
- } catch (ArrayIndexOutOfBoundsException e) {
- System.out.println(":SendKey (ACTION_UP): " + lastKey + " // Unknown key event");
- }
- }
- try {
- if (! mWm.injectKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, lastKey), false)) {
+ MonkeyEvent ev = mEventSource.getNextEvent();
+ if (ev != null) {
+ i++;
+ int injectCode = ev.injectEvent(mWm, mAm, mVerbose);
+ if (injectCode == MonkeyEvent.INJECT_FAIL) {
+ if (ev instanceof MonkeyKeyEvent) {
mDroppedKeyEvents++;
+ } else if (ev instanceof MonkeyMotionEvent) {
+ mDroppedPointerEvents++;
+ } else if (ev instanceof MonkeyFlipEvent) {
+ mDroppedFlipEvents++;
}
- } catch (RemoteException ex) {
+ } else if (injectCode == MonkeyEvent.INJECT_ERROR_REMOTE_EXCEPTION) {
systemCrashed = true;
- break;
+ } else if (injectCode == MonkeyEvent.INJECT_ERROR_SECURITY_EXCEPTION) {
+ systemCrashed = !mIgnoreSecurityExceptions;
}
- lastKey = 0;
- i++;
- continue;
- }
-
- // otherwise begin a new event cycle
- float cls = random.nextFloat();
-
- boolean touchEvent = cls < mFactors[FACTOR_TOUCH];
- boolean motionEvent = !touchEvent && (cls < mFactors[FACTOR_MOTION]);
- if (touchEvent || motionEvent) {
- try {
- generateMotionEvent(random, motionEvent);
- } catch (RemoteException ex) {
- systemCrashed = true;
- break;
- }
- i++;
- continue;
- }
-
- if (cls < mFactors[FACTOR_TRACKBALL]) {
- try {
- generateTrackballEvent(random);
- } catch (RemoteException ex) {
- systemCrashed = true;
- break;
- }
- i++;
- continue;
- }
-
- // The remaining event categories are injected as key events
- if (cls < mFactors[FACTOR_NAV]) {
- lastKey = NAV_KEYS[random.nextInt(NAV_KEYS.length)];
- } else if (cls < mFactors[FACTOR_MAJORNAV]) {
- lastKey = MAJOR_NAV_KEYS[random.nextInt(MAJOR_NAV_KEYS.length)];
- } else if (cls < mFactors[FACTOR_SYSOPS]) {
- lastKey = SYS_KEYS[random.nextInt(SYS_KEYS.length)];
- } else if (cls < mFactors[FACTOR_APPSWITCH]) {
- if (!startRandomActivity(random)) {
- systemCrashed = true;
- break;
- }
- i++;
- continue;
- } else {
- lastKey = 1 + random.nextInt(KeyEvent.MAX_KEYCODE - 1);
- }
- if (mVerbose > 0) {
- try {
- System.out.println(":SendKey: " + lastKey + " // " + KEY_NAMES[lastKey]);
- } catch (ArrayIndexOutOfBoundsException e) {
- System.out.println(":SendKey: " + lastKey + " // Unknown key event");
- }
- }
- try {
- if (! mWm.injectKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, lastKey), false)) {
- mDroppedKeyEvents++;
- }
- } catch (RemoteException ex) {
- systemCrashed = true;
- break;
}
}
-
+
// If we got this far, we succeeded!
return mCount;
}
/**
- * Generates a random motion event. This method counts a down, move, and up as one event.
- *
- * TODO: Test & fix the selectors when non-zero percentages
- * TODO: Longpress.
- * TODO: Fling.
- * TODO: Meta state
- * TODO: More useful than the random walk here would be to pick a single random direction
- * and distance, and divvy it up into a random number of segments. (This would serve to
- * generate fling gestures, which are important).
- *
- * @param random Random number source for positioning
- * @param motionEvent If false, touch/release. If true, touch/move/release.
- *
- * @throws RemoteException
- */
- private void generateMotionEvent(Random random, boolean motionEvent) throws RemoteException {
- Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
-
- float x = Math.abs(random.nextInt() % display.getWidth());
- float y = Math.abs(random.nextInt() % display.getHeight());
- long downAt = SystemClock.uptimeMillis();
- boolean drop = false;
- drop = sendMotionEvent(MotionEvent.ACTION_DOWN, x, y, downAt, "Pointer ACTION_DOWN", false,
- true);
-
- // sometimes we'll move during the touch
- if (motionEvent) {
- int count = random.nextInt(10);
- for (int i = 0 ; i < count ; i++) {
- // generate some slop in the up event
- x = (x + (random.nextInt() % 10)) % display.getWidth();
- y = (y + (random.nextInt() % 10)) % display.getHeight();
- drop |= sendMotionEvent(MotionEvent.ACTION_MOVE, x, y, downAt,
- "Pointer ACTION_MOVE", true, true);
- }
- }
-
- // TODO generate some slop in the up event
- drop |= sendMotionEvent(MotionEvent.ACTION_UP, x, y, downAt, "Pointer ACTION_UP", false,
- true);
-
- if (drop) {
- mDroppedPointerEvents++;
- }
- }
-
- /**
- * Sends a single motion event, either as a pointer or a trackball.
- *
- * @param action Must be one of the ACTION values defined in {@link MotionEvent}
- * @param x The position, or movement, in the X axis
- * @param y The position, or movement, in the Y axis
- * @param downAt The time of the first DOWN must be sent here, and the same value must
- * be sent for all subsequent events that are related (through the eventual UP event), or
- * -1 to simply send the current time as the downTime.
- * @param note This will be displayed when in verbose mode
- * @param intermediateNote If true, this is an intermediate step (more verbose logging, only)
- * @param isPointer Use true to send a pointer event, and false to send a trackball event
- *
- * @return Returns false if event was dispatched, true if it was dropped for any reason
- *
- * @throws RemoteException
- */
- private boolean sendMotionEvent(int action, float x, float y, long downAt, final String note,
- boolean intermediateNote, boolean isPointer) throws RemoteException {
- if ((mVerbose > 0 && !intermediateNote) || mVerbose > 1) {
- System.out.println(":Sending " + note + " x=" + x + " y=" + y);
- }
- long eventTime = SystemClock.uptimeMillis();
- if (downAt == -1) {
- downAt = eventTime;
- }
- final MotionEvent evt = MotionEvent.obtain(downAt, eventTime, action, x, y, 0);
- if (isPointer) {
- return ! mWm.injectPointerEvent(evt, false);
- } else {
- return ! mWm.injectTrackballEvent(evt, false);
- }
- }
-
- /**
- * Generates a random trackball event. This consists of a sequence of small moves, followed by
- * an optional single click.
- *
- * TODO: Longpress.
- * TODO: Meta state
- * TODO: Parameterize the % clicked
- * TODO: More useful than the random walk here would be to pick a single random direction
- * and distance, and divvy it up into a random number of segments. (This would serve to
- * generate fling gestures, which are important).
- *
- * @param random Random number source for positioning
- *
- * @throws RemoteException
- */
- private void generateTrackballEvent(Random random) throws RemoteException {
- Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
-
- boolean drop = false;
- int count = random.nextInt(10);
- for (int i = 0; i < 10; ++i) {
- // generate a small random step
- int dX = random.nextInt(10) - 5;
- int dY = random.nextInt(10) - 5;
- drop |= sendMotionEvent(MotionEvent.ACTION_MOVE, dX, dY, -1, "Trackball ACTION_MOVE",
- (i > 0), false);
- }
-
- // 10% of trackball moves end with a click
- if (0 == random.nextInt(10)) {
- long downAt = SystemClock.uptimeMillis();
- drop |= sendMotionEvent(MotionEvent.ACTION_DOWN, 0, 0, downAt, "Trackball ACTION_DOWN",
- true, false);
- drop |= sendMotionEvent(MotionEvent.ACTION_UP, 0, 0, downAt, "Trackball ACTION_UP",
- false, false);
- }
-
- if (drop) {
- mDroppedTrackballEvents++;
- }
- }
-
- /**
* Send SIGNAL_USR1 to all processes. This will generate large (5mb) profiling reports
* in data/misc, so use with care.
*/
@@ -1121,40 +770,6 @@
}
/**
- * Have the activity manager start a new activity.
- *
- * @param random Random number source
- *
- * @return Returns true on success, false if there was an error calling
- * the activity manager.
- */
- private boolean startRandomActivity(Random random) {
- int numApps = mMainApps.size();
- int which = random.nextInt(numApps);
- ComponentName app = mMainApps.get(which);
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.addCategory(Intent.CATEGORY_LAUNCHER);
- intent.setComponent(app);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- if (mVerbose > 0) {
- System.out.println(":Switch: " + intent.toURI());
- }
- try {
- mAm.startActivity(null, intent, null, null, 0, null, null, 0, false, false);
- } catch (RemoteException e) {
- System.err.println("** Failed talking with activity manager!");
- return false;
- } catch (SecurityException e) {
- if (mVerbose > 0) {
- System.out.println("** Permissions error starting activity " + intent.toURI());
- }
- return mIgnoreSecurityExceptions; // true = "launched ok" (pretend)
- }
- return true;
- }
-
- /**
* Watch for appearance of new tombstone files, which indicate native crashes.
*
* @return Returns true if new files have appeared in the list
@@ -1185,7 +800,7 @@
/**
* Return the next command line option. This has a number of special cases which
* closely, but not exactly, follow the POSIX command line options patterns:
- *
+ *
* -- means to stop processing additional options
* -z means option z
* -z ARGS means option z with (non-optional) arguments ARGS
@@ -1274,17 +889,18 @@
* Print how to use this command.
*/
private void showUsage() {
- System.err.println("usage: monkey [-p ALLOWED_PACKAGE [-p ALLOWED_PACKAGE] ...]");
- System.err.println(" [-c MAIN_CATEGORY [-c MAIN_CATEGORY] ...]");
- System.err.println(" [--ignore-crashes] [--ignore-timeouts]");
- System.err.println(" [--ignore-security-exceptions] [--monitor-native-crashes]");
- System.err.println(" [--kill-process-after-error] [--hprof]");
- System.err.println(" [--pct-touch PERCENT] [--pct-motion PERCENT]");
- System.err.println(" [--pct-trackball PERCENT] [--pct-syskeys PERCENT]");
- System.err.println(" [--pct-nav PERCENT] [--pct-majornav PERCENT]");
- System.err.println(" [--pct-appswitch PERCENT] [--pct-anyevent PERCENT]");
- System.err.println(" [--wait-dbg] [--dbg-no-events]");
- System.err.println(" [-s SEED] [-v [-v] ...] [--throttle MILLISEC]");
- System.err.println(" COUNT");
- }
+ System.err.println("usage: monkey [-p ALLOWED_PACKAGE [-p ALLOWED_PACKAGE] ...]");
+ System.err.println(" [-c MAIN_CATEGORY [-c MAIN_CATEGORY] ...]");
+ System.err.println(" [--ignore-crashes] [--ignore-timeouts]");
+ System.err.println(" [--ignore-security-exceptions] [--monitor-native-crashes]");
+ System.err.println(" [--kill-process-after-error] [--hprof]");
+ System.err.println(" [--pct-touch PERCENT] [--pct-motion PERCENT]");
+ System.err.println(" [--pct-trackball PERCENT] [--pct-syskeys PERCENT]");
+ System.err.println(" [--pct-nav PERCENT] [--pct-majornav PERCENT]");
+ System.err.println(" [--pct-appswitch PERCENT] [--pct-flip PERCENT]");
+ System.err.println(" [--pct-anyevent PERCENT]");
+ System.err.println(" [--wait-dbg] [--dbg-no-events] [-f scriptfile]");
+ System.err.println(" [-s SEED] [-v [-v] ...] [--throttle MILLISEC]");
+ System.err.println(" COUNT");
+ }
}
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyActivityEvent.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyActivityEvent.java
new file mode 100644
index 0000000..68e6e6d
--- /dev/null
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeyActivityEvent.java
@@ -0,0 +1,68 @@
+/*
+ * 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.commands.monkey;
+
+import android.app.IActivityManager;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.RemoteException;
+import android.view.IWindowManager;
+
+/**
+ * monkey activity event
+ */
+public class MonkeyActivityEvent extends MonkeyEvent {
+ private ComponentName mApp;
+
+ public MonkeyActivityEvent(ComponentName app) {
+ super(EVENT_TYPE_ACTIVITY);
+ mApp = app;
+ }
+
+ /**
+ * @return Intent for the new activity
+ */
+ private Intent getEvent() {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
+ intent.setComponent(mApp);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ return intent;
+ }
+
+ @Override
+ public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) {
+ Intent intent = getEvent();
+ if (verbose > 0) {
+ System.out.println(":Switch: " + intent.toURI());
+ }
+ try {
+ iam.startActivity(null, intent, null, null, 0, null, null, 0,
+ false, false);
+ } catch (RemoteException e) {
+ System.err.println("** Failed talking with activity manager!");
+ return MonkeyEvent.INJECT_ERROR_REMOTE_EXCEPTION;
+ } catch (SecurityException e) {
+ if (verbose > 0) {
+ System.out.println("** Permissions error starting activity "
+ + intent.toURI());
+ }
+ return MonkeyEvent.INJECT_ERROR_SECURITY_EXCEPTION;
+ }
+ return MonkeyEvent.INJECT_SUCCESS;
+ }
+}
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyEvent.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyEvent.java
new file mode 100644
index 0000000..ff99f5f
--- /dev/null
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeyEvent.java
@@ -0,0 +1,61 @@
+/*
+ * 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.commands.monkey;
+
+import android.app.IActivityManager;
+import android.view.IWindowManager;
+
+/**
+ * abstract class for monkey event
+ */
+public abstract class MonkeyEvent {
+ protected int eventType;
+ public static final int EVENT_TYPE_KEY = 0;
+ public static final int EVENT_TYPE_POINTER = 1;
+ public static final int EVENT_TYPE_TRACKBALL = 2;
+ public static final int EVENT_TYPE_ACTIVITY = 3;
+ public static final int EVENT_TYPE_FLIP = 4; // Keyboard flip
+
+ public static final int INJECT_SUCCESS = 1;
+ public static final int INJECT_FAIL = 0;
+
+ // error code for remote exception during injection
+ public static final int INJECT_ERROR_REMOTE_EXCEPTION = -1;
+ // error code for security exception during injection
+ public static final int INJECT_ERROR_SECURITY_EXCEPTION = -2;
+
+ public MonkeyEvent(int type) {
+ eventType = type;
+ }
+
+ /**
+ * @return event type
+ */
+ public int getEventType() {
+ return eventType;
+ }
+
+ /**
+ * a method for injecting event
+ * @param iwm wires to current window manager
+ * @param iam wires to current activity manager
+ * @param verbose a log switch
+ * @return INJECT_SUCCESS if it goes through, and INJECT_FAIL if it fails
+ * in the case of exceptions, return its corresponding error code
+ */
+ public abstract int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose);
+}
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyEventSource.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyEventSource.java
new file mode 100644
index 0000000..a236554
--- /dev/null
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeyEventSource.java
@@ -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.commands.monkey;
+
+/**
+ * event source interface
+ */
+public interface MonkeyEventSource {
+ /**
+ *
+ * @return the next monkey event from the source
+ */
+ public MonkeyEvent getNextEvent();
+
+ /**
+ * set verbose to allow different level of log
+ * @param verbose output mode? 1= verbose, 2=very verbose
+ */
+ public void setVerbose(int verbose);
+
+ /**
+ * check whether precondition is satisfied
+ * @return false if something fails, e.g. factor failure in random source
+ * or file can not open from script source etc
+ */
+ public boolean validate();
+}
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyFlipEvent.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyFlipEvent.java
new file mode 100644
index 0000000..08fbedb
--- /dev/null
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeyFlipEvent.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2008 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.commands.monkey;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import android.app.IActivityManager;
+import android.view.IWindowManager;
+/**
+ * monkey keyboard flip event
+ */
+public class MonkeyFlipEvent extends MonkeyEvent {
+
+ // Raw keyboard flip event data
+ // Works on emulator and dream
+
+ private static final byte[] FLIP_0 = {
+ 0x7f, 0x06,
+ 0x00, 0x00,
+ (byte) 0xe0, 0x39,
+ 0x01, 0x00,
+ 0x05, 0x00,
+ 0x00, 0x00,
+ 0x01, 0x00,
+ 0x00, 0x00 };
+
+ private static final byte[] FLIP_1 = {
+ (byte) 0x85, 0x06,
+ 0x00, 0x00,
+ (byte) 0x9f, (byte) 0xa5,
+ 0x0c, 0x00,
+ 0x05, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00 };
+
+ private final boolean mKeyboardOpen;
+
+ public MonkeyFlipEvent(boolean keyboardOpen) {
+ super(EVENT_TYPE_FLIP);
+ mKeyboardOpen = keyboardOpen;
+ }
+
+ @Override
+ public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) {
+ if (verbose > 0) {
+ System.out.println(":Sending Flip keyboardOpen=" + mKeyboardOpen);
+ }
+
+ // inject flip event
+ try {
+ FileOutputStream f = new FileOutputStream("/dev/input/event0");
+ f.write(mKeyboardOpen ? FLIP_0 : FLIP_1);
+ f.close();
+ return MonkeyEvent.INJECT_SUCCESS;
+ } catch (IOException e) {
+ System.out.println("Got IOException performing flip" + e);
+ return MonkeyEvent.INJECT_FAIL;
+ }
+ }
+}
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyKeyEvent.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyKeyEvent.java
new file mode 100644
index 0000000..c1e0ffc
--- /dev/null
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeyKeyEvent.java
@@ -0,0 +1,125 @@
+/*
+ * 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.commands.monkey;
+
+import android.app.IActivityManager;
+import android.os.RemoteException;
+import android.view.IWindowManager;
+import android.view.KeyEvent;
+/**
+ * monkey key event
+ */
+public class MonkeyKeyEvent extends MonkeyEvent {
+ private long mDownTime = -1;
+ private int mMetaState = -1;
+ private int mAction = -1;
+ private int mKeyCode = -1;
+ private int mScancode = -1;
+ private int mRepeatCount = -1;
+ private int mDeviceId = -1;
+ private long mEventTime = -1;
+
+ public MonkeyKeyEvent(int action, int keycode) {
+ super(EVENT_TYPE_KEY);
+ mAction = action;
+ mKeyCode = keycode;
+ }
+
+ public MonkeyKeyEvent(long downTime, long eventTime, int action,
+ int code, int repeat, int metaState,
+ int device, int scancode) {
+ super(EVENT_TYPE_KEY);
+
+ mAction = action;
+ mKeyCode = code;
+ mMetaState = metaState;
+ mScancode = scancode;
+ mRepeatCount = repeat;
+ mDeviceId = device;
+ mDownTime = downTime;
+ mEventTime = eventTime;
+ }
+
+ public int getKeyCode() {
+ return mKeyCode;
+ }
+
+ public int getAction() {
+ return mAction;
+ }
+
+ public long getDownTime() {
+ return mDownTime;
+ }
+
+ public long getEventTime() {
+ return mEventTime;
+ }
+
+ public void setDownTime(long downTime) {
+ mDownTime = downTime;
+ }
+
+ public void setEventTime(long eventTime) {
+ mEventTime = eventTime;
+ }
+
+ /**
+ * @return the key event
+ */
+ private KeyEvent getEvent() {
+ if (mDeviceId < 0) {
+ return new KeyEvent(mAction, mKeyCode);
+ }
+
+ // for scripts
+ return new KeyEvent(mDownTime, mEventTime, mAction,
+ mKeyCode, mRepeatCount, mMetaState, mDeviceId, mScancode);
+ }
+
+ @Override
+ public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) {
+ if (verbose > 1) {
+ String note;
+ if (mAction == KeyEvent.ACTION_UP) {
+ note = "ACTION_UP";
+ } else {
+ note = "ACTION_DOWN";
+ }
+
+ try {
+ System.out.println(":SendKey (" + note + "): "
+ + mKeyCode + " // "
+ + MonkeySourceRandom.getKeyName(mKeyCode));
+ } catch (ArrayIndexOutOfBoundsException e) {
+ System.out.println(":SendKey (ACTION_UP): "
+ + mKeyCode + " // Unknown key event");
+ }
+ }
+
+ // inject key event
+ try {
+ if (!iwm.injectKeyEvent(getEvent(), false)) {
+ return MonkeyEvent.INJECT_FAIL;
+ }
+ } catch (RemoteException ex) {
+ return MonkeyEvent.INJECT_ERROR_REMOTE_EXCEPTION;
+ }
+
+ return MonkeyEvent.INJECT_SUCCESS;
+ }
+}
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyMotionEvent.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyMotionEvent.java
new file mode 100644
index 0000000..2657061
--- /dev/null
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeyMotionEvent.java
@@ -0,0 +1,156 @@
+/*
+ * 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.commands.monkey;
+
+import android.app.IActivityManager;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.view.IWindowManager;
+import android.view.MotionEvent;
+
+
+/**
+ * monkey motion event
+ */
+public class MonkeyMotionEvent extends MonkeyEvent {
+ private long mDownTime = -1;
+ private long mEventTime = -1;
+ private int mAction = -1;
+ private float mX = -1;
+ private float mY = -1;
+ private float mPressure = -1;
+ private float mSize = -1;
+ private int mMetaState = -1;
+ private float mXPrecision = -1;
+ private float mYPrecision = -1;
+ private int mDeviceId = -1;
+ private int mEdgeFlags = -1;
+
+ //If true, this is an intermediate step (more verbose logging, only)
+ private boolean mIntermediateNote;
+
+ public MonkeyMotionEvent(int type, long downAt, int action,
+ float x, float y, int metaState) {
+ super(type);
+ mDownTime = downAt;
+ mAction = action;
+ mX = x;
+ mY = y;
+ mMetaState = metaState;
+ }
+
+ public MonkeyMotionEvent(int type, long downTime, long eventTime, int action,
+ float x, float y, float pressure, float size, int metaState,
+ float xPrecision, float yPrecision, int deviceId, int edgeFlags) {
+ super(type);
+ mDownTime = downTime;
+ mEventTime = eventTime;
+ mAction = action;
+ mX = x;
+ mY = y;
+ mPressure = pressure;
+ mSize = size;
+ mMetaState = metaState;
+ mXPrecision = xPrecision;
+ mYPrecision = yPrecision;
+ mDeviceId = deviceId;
+ mEdgeFlags = edgeFlags;
+ }
+
+ public void setIntermediateNote(boolean b) {
+ mIntermediateNote = b;
+ }
+
+ public boolean getIntermediateNote() {
+ return mIntermediateNote;
+ }
+
+ public float getX() {
+ return mX;
+ }
+
+ public float getY() {
+ return mY;
+ }
+
+ public int getAction() {
+ return mAction;
+ }
+
+ public long getDownTime() {
+ return mDownTime;
+ }
+
+ public long getEventTime() {
+ return mEventTime;
+ }
+
+ public void setDownTime(long downTime) {
+ mDownTime = downTime;
+ }
+
+ public void setEventTime(long eventTime) {
+ mEventTime = eventTime;
+ }
+
+ /**
+ *
+ * @return instance of a motion event
+ */
+ private MotionEvent getEvent() {
+ if (mDeviceId < 0) {
+ return MotionEvent.obtain(mDownTime, SystemClock.uptimeMillis(),
+ mAction, mX, mY, mMetaState);
+ }
+
+ // for scripts
+ return MotionEvent.obtain(mDownTime, mEventTime,
+ mAction, mX, mY, mPressure, mSize, mMetaState,
+ mXPrecision, mYPrecision, mDeviceId, mEdgeFlags);
+ }
+
+ @Override
+ public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) {
+
+ String note;
+ if ((verbose > 0 && !mIntermediateNote) || verbose > 1) {
+ if (mAction == MotionEvent.ACTION_DOWN) {
+ note = "DOWN";
+ } else if (mAction == MotionEvent.ACTION_UP) {
+ note = "UP";
+ } else {
+ note = "MOVE";
+ }
+ System.out.println(":Sending Pointer ACTION_" + note +
+ " x=" + mX + " y=" + mY);
+ }
+ try {
+ int type = this.getEventType();
+ MotionEvent me = getEvent();
+
+ if ((type == MonkeyEvent.EVENT_TYPE_POINTER &&
+ !iwm.injectPointerEvent(me, false))
+ || (type == MonkeyEvent.EVENT_TYPE_TRACKBALL &&
+ !iwm.injectTrackballEvent(me, false))) {
+ return MonkeyEvent.INJECT_FAIL;
+ }
+ } catch (RemoteException ex) {
+ return MonkeyEvent.INJECT_ERROR_REMOTE_EXCEPTION;
+ }
+ return MonkeyEvent.INJECT_SUCCESS;
+ }
+}
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java
new file mode 100644
index 0000000..dd92846
--- /dev/null
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java
@@ -0,0 +1,465 @@
+/*
+ * 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.commands.monkey;
+
+import android.content.ComponentName;
+import android.os.SystemClock;
+import android.view.Display;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.WindowManagerImpl;
+
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.Random;
+
+/**
+ * monkey event queue
+ */
+public class MonkeySourceRandom implements MonkeyEventSource{
+ /** Key events that move around the UI. */
+ private static final int[] NAV_KEYS = {
+ KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN,
+ KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_RIGHT,
+ };
+ /**
+ * Key events that perform major navigation options (so shouldn't be sent
+ * as much).
+ */
+ private static final int[] MAJOR_NAV_KEYS = {
+ KeyEvent.KEYCODE_MENU, /*KeyEvent.KEYCODE_SOFT_RIGHT,*/
+ KeyEvent.KEYCODE_DPAD_CENTER,
+ };
+ /** Key events that perform system operations. */
+ private static final int[] SYS_KEYS = {
+ KeyEvent.KEYCODE_HOME, KeyEvent.KEYCODE_BACK,
+ KeyEvent.KEYCODE_CALL, KeyEvent.KEYCODE_ENDCALL,
+ KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_VOLUME_DOWN,
+ };
+ /** Nice names for all key events. */
+ private static final String[] KEY_NAMES = {
+ "KEYCODE_UNKNOWN",
+ "KEYCODE_MENU",
+ "KEYCODE_SOFT_RIGHT",
+ "KEYCODE_HOME",
+ "KEYCODE_BACK",
+ "KEYCODE_CALL",
+ "KEYCODE_ENDCALL",
+ "KEYCODE_0",
+ "KEYCODE_1",
+ "KEYCODE_2",
+ "KEYCODE_3",
+ "KEYCODE_4",
+ "KEYCODE_5",
+ "KEYCODE_6",
+ "KEYCODE_7",
+ "KEYCODE_8",
+ "KEYCODE_9",
+ "KEYCODE_STAR",
+ "KEYCODE_POUND",
+ "KEYCODE_DPAD_UP",
+ "KEYCODE_DPAD_DOWN",
+ "KEYCODE_DPAD_LEFT",
+ "KEYCODE_DPAD_RIGHT",
+ "KEYCODE_DPAD_CENTER",
+ "KEYCODE_VOLUME_UP",
+ "KEYCODE_VOLUME_DOWN",
+ "KEYCODE_POWER",
+ "KEYCODE_CAMERA",
+ "KEYCODE_CLEAR",
+ "KEYCODE_A",
+ "KEYCODE_B",
+ "KEYCODE_C",
+ "KEYCODE_D",
+ "KEYCODE_E",
+ "KEYCODE_F",
+ "KEYCODE_G",
+ "KEYCODE_H",
+ "KEYCODE_I",
+ "KEYCODE_J",
+ "KEYCODE_K",
+ "KEYCODE_L",
+ "KEYCODE_M",
+ "KEYCODE_N",
+ "KEYCODE_O",
+ "KEYCODE_P",
+ "KEYCODE_Q",
+ "KEYCODE_R",
+ "KEYCODE_S",
+ "KEYCODE_T",
+ "KEYCODE_U",
+ "KEYCODE_V",
+ "KEYCODE_W",
+ "KEYCODE_X",
+ "KEYCODE_Y",
+ "KEYCODE_Z",
+ "KEYCODE_COMMA",
+ "KEYCODE_PERIOD",
+ "KEYCODE_ALT_LEFT",
+ "KEYCODE_ALT_RIGHT",
+ "KEYCODE_SHIFT_LEFT",
+ "KEYCODE_SHIFT_RIGHT",
+ "KEYCODE_TAB",
+ "KEYCODE_SPACE",
+ "KEYCODE_SYM",
+ "KEYCODE_EXPLORER",
+ "KEYCODE_ENVELOPE",
+ "KEYCODE_ENTER",
+ "KEYCODE_DEL",
+ "KEYCODE_GRAVE",
+ "KEYCODE_MINUS",
+ "KEYCODE_EQUALS",
+ "KEYCODE_LEFT_BRACKET",
+ "KEYCODE_RIGHT_BRACKET",
+ "KEYCODE_BACKSLASH",
+ "KEYCODE_SEMICOLON",
+ "KEYCODE_APOSTROPHE",
+ "KEYCODE_SLASH",
+ "KEYCODE_AT",
+ "KEYCODE_NUM",
+ "KEYCODE_HEADSETHOOK",
+ "KEYCODE_FOCUS",
+ "KEYCODE_PLUS",
+ "KEYCODE_MENU",
+ "KEYCODE_NOTIFICATION",
+ "KEYCODE_SEARCH",
+ "KEYCODE_PLAYPAUSE",
+ "KEYCODE_STOP",
+ "KEYCODE_NEXTSONG",
+ "KEYCODE_PREVIOUSSONG",
+ "KEYCODE_REWIND",
+ "KEYCODE_FORWARD",
+
+ "TAG_LAST_KEYCODE" // EOL. used to keep the lists in sync
+ };
+
+ public static final int FACTOR_TOUCH = 0;
+ public static final int FACTOR_MOTION = 1;
+ public static final int FACTOR_TRACKBALL = 2;
+ public static final int FACTOR_NAV = 3;
+ public static final int FACTOR_MAJORNAV = 4;
+ public static final int FACTOR_SYSOPS = 5;
+ public static final int FACTOR_APPSWITCH = 6;
+ public static final int FACTOR_FLIP = 7;
+ public static final int FACTOR_ANYTHING = 8;
+ public static final int FACTORZ_COUNT = 9; // should be last+1
+
+
+ /** percentages for each type of event. These will be remapped to working
+ * values after we read any optional values.
+ **/
+ private float[] mFactors = new float[FACTORZ_COUNT];
+ private ArrayList<ComponentName> mMainApps;
+ private int mEventCount = 0; //total number of events generated so far
+ private LinkedList<MonkeyEvent> mQ = new LinkedList<MonkeyEvent>();
+ private Random mRandom;
+ private int mVerbose = 0;
+
+ private boolean mKeyboardOpen = false;
+
+ /**
+ * @return the last name in the key list
+ */
+ public static String getLastKeyName() {
+ return KEY_NAMES[KeyEvent.getMaxKeyCode() + 1];
+ }
+
+ public static String getKeyName(int keycode) {
+ return KEY_NAMES[keycode];
+ }
+
+ public MonkeySourceRandom(long seed, ArrayList<ComponentName> MainApps) {
+ // default values for random distributions
+ // note, these are straight percentages, to match user input (cmd line args)
+ // but they will be converted to 0..1 values before the main loop runs.
+ mFactors[FACTOR_TOUCH] = 15.0f;
+ mFactors[FACTOR_MOTION] = 10.0f;
+ mFactors[FACTOR_TRACKBALL] = 15.0f;
+ mFactors[FACTOR_NAV] = 25.0f;
+ mFactors[FACTOR_MAJORNAV] = 15.0f;
+ mFactors[FACTOR_SYSOPS] = 2.0f;
+ mFactors[FACTOR_APPSWITCH] = 2.0f;
+ mFactors[FACTOR_FLIP] = 1.0f;
+ mFactors[FACTOR_ANYTHING] = 15.0f;
+
+ mRandom = new SecureRandom();
+ mRandom.setSeed((seed == 0) ? -1 : seed);
+ mMainApps = MainApps;
+ }
+
+ /**
+ * Adjust the percentages (after applying user values) and then normalize to a 0..1 scale.
+ */
+ private boolean adjustEventFactors() {
+ // go through all values and compute totals for user & default values
+ float userSum = 0.0f;
+ float defaultSum = 0.0f;
+ int defaultCount = 0;
+ for (int i = 0; i < FACTORZ_COUNT; ++i) {
+ if (mFactors[i] <= 0.0f) { // user values are zero or negative
+ userSum -= mFactors[i];
+ } else {
+ defaultSum += mFactors[i];
+ ++defaultCount;
+ }
+ }
+
+ // if the user request was > 100%, reject it
+ if (userSum > 100.0f) {
+ System.err.println("** Event weights > 100%");
+ return false;
+ }
+
+ // if the user specified all of the weights, then they need to be 100%
+ if (defaultCount == 0 && (userSum < 99.9f || userSum > 100.1f)) {
+ System.err.println("** Event weights != 100%");
+ return false;
+ }
+
+ // compute the adjustment necessary
+ float defaultsTarget = (100.0f - userSum);
+ float defaultsAdjustment = defaultsTarget / defaultSum;
+
+ // fix all values, by adjusting defaults, or flipping user values back to >0
+ for (int i = 0; i < FACTORZ_COUNT; ++i) {
+ if (mFactors[i] <= 0.0f) { // user values are zero or negative
+ mFactors[i] = -mFactors[i];
+ } else {
+ mFactors[i] *= defaultsAdjustment;
+ }
+ }
+
+ // if verbose, show factors
+
+ if (mVerbose > 0) {
+ System.out.println("// Event percentages:");
+ for (int i = 0; i < FACTORZ_COUNT; ++i) {
+ System.out.println("// " + i + ": " + mFactors[i] + "%");
+ }
+ }
+
+ // finally, normalize and convert to running sum
+ float sum = 0.0f;
+ for (int i = 0; i < FACTORZ_COUNT; ++i) {
+ sum += mFactors[i] / 100.0f;
+ mFactors[i] = sum;
+ }
+ return true;
+ }
+
+ /**
+ * set the factors
+ *
+ * @param factors: percentages for each type of event
+ */
+ public void setFactors(float factors[]) {
+ int c = FACTORZ_COUNT;
+ if (factors.length < c) {
+ c = factors.length;
+ }
+ for (int i = 0; i < c; i++)
+ mFactors[i] = factors[i];
+ }
+
+ public void setFactors(int index, float v) {
+ mFactors[index] = v;
+ }
+
+ /**
+ * Generates a random motion event. This method counts a down, move, and up as multiple events.
+ *
+ * TODO: Test & fix the selectors when non-zero percentages
+ * TODO: Longpress.
+ * TODO: Fling.
+ * TODO: Meta state
+ * TODO: More useful than the random walk here would be to pick a single random direction
+ * and distance, and divvy it up into a random number of segments. (This would serve to
+ * generate fling gestures, which are important).
+ *
+ * @param random Random number source for positioning
+ * @param motionEvent If false, touch/release. If true, touch/move/release.
+ *
+ */
+ private void generateMotionEvent(Random random, boolean motionEvent){
+
+ Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
+
+ float x = Math.abs(random.nextInt() % display.getWidth());
+ float y = Math.abs(random.nextInt() % display.getHeight());
+ long downAt = SystemClock.uptimeMillis();
+ long eventTime = SystemClock.uptimeMillis();
+ if (downAt == -1) {
+ downAt = eventTime;
+ }
+
+ MonkeyMotionEvent e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER,
+ downAt, MotionEvent.ACTION_DOWN, x, y, 0);
+ e.setIntermediateNote(false);
+ mQ.addLast(e);
+
+ // sometimes we'll move during the touch
+ if (motionEvent) {
+ int count = random.nextInt(10);
+ for (int i = 0; i < count; i++) {
+ // generate some slop in the up event
+ x = (x + (random.nextInt() % 10)) % display.getWidth();
+ y = (y + (random.nextInt() % 10)) % display.getHeight();
+
+ e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER,
+ downAt, MotionEvent.ACTION_MOVE, x, y, 0);
+ e.setIntermediateNote(true);
+ mQ.addLast(e);
+ }
+ }
+
+ // TODO generate some slop in the up event
+ e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER,
+ downAt, MotionEvent.ACTION_UP, x, y, 0);
+ e.setIntermediateNote(false);
+ mQ.addLast(e);
+ }
+
+ /**
+ * Generates a random trackball event. This consists of a sequence of small moves, followed by
+ * an optional single click.
+ *
+ * TODO: Longpress.
+ * TODO: Meta state
+ * TODO: Parameterize the % clicked
+ * TODO: More useful than the random walk here would be to pick a single random direction
+ * and distance, and divvy it up into a random number of segments. (This would serve to
+ * generate fling gestures, which are important).
+ *
+ * @param random Random number source for positioning
+ *
+ */
+ private void generateTrackballEvent(Random random) {
+ Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
+
+ boolean drop = false;
+ int count = random.nextInt(10);
+ MonkeyMotionEvent e;
+ for (int i = 0; i < 10; ++i) {
+ // generate a small random step
+ int dX = random.nextInt(10) - 5;
+ int dY = random.nextInt(10) - 5;
+
+
+ e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_TRACKBALL, -1,
+ MotionEvent.ACTION_MOVE, dX, dY, 0);
+ e.setIntermediateNote(i > 0);
+ mQ.addLast(e);
+ }
+
+ // 10% of trackball moves end with a click
+ if (0 == random.nextInt(10)) {
+ long downAt = SystemClock.uptimeMillis();
+
+
+ e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_TRACKBALL, downAt,
+ MotionEvent.ACTION_DOWN, 0, 0, 0);
+ e.setIntermediateNote(true);
+ mQ.addLast(e);
+
+
+ e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_TRACKBALL, downAt,
+ MotionEvent.ACTION_UP, 0, 0, 0);
+ e.setIntermediateNote(false);
+ mQ.addLast(e);
+ }
+ }
+
+ /**
+ * generate a random event based on mFactor
+ */
+ private void generateEvents() {
+ float cls = mRandom.nextFloat();
+ int lastKey = 0;
+
+ boolean touchEvent = cls < mFactors[FACTOR_TOUCH];
+ boolean motionEvent = !touchEvent && (cls < mFactors[FACTOR_MOTION]);
+ if (touchEvent || motionEvent) {
+ generateMotionEvent(mRandom, motionEvent);
+ return;
+ }
+
+ if (cls < mFactors[FACTOR_TRACKBALL]) {
+ generateTrackballEvent(mRandom);
+ return;
+ }
+
+ // The remaining event categories are injected as key events
+ if (cls < mFactors[FACTOR_NAV]) {
+ lastKey = NAV_KEYS[mRandom.nextInt(NAV_KEYS.length)];
+ } else if (cls < mFactors[FACTOR_MAJORNAV]) {
+ lastKey = MAJOR_NAV_KEYS[mRandom.nextInt(MAJOR_NAV_KEYS.length)];
+ } else if (cls < mFactors[FACTOR_SYSOPS]) {
+ lastKey = SYS_KEYS[mRandom.nextInt(SYS_KEYS.length)];
+ } else if (cls < mFactors[FACTOR_APPSWITCH]) {
+ MonkeyActivityEvent e = new MonkeyActivityEvent(mMainApps.get(
+ mRandom.nextInt(mMainApps.size())));
+ mQ.addLast(e);
+ return;
+ } else if (cls < mFactors[FACTOR_FLIP]) {
+ MonkeyFlipEvent e = new MonkeyFlipEvent(mKeyboardOpen);
+ mKeyboardOpen = !mKeyboardOpen;
+ mQ.addLast(e);
+ return;
+ } else {
+ lastKey = 1 + mRandom.nextInt(KeyEvent.getMaxKeyCode() - 1);
+ }
+
+ MonkeyKeyEvent e = new MonkeyKeyEvent(KeyEvent.ACTION_DOWN, lastKey);
+ mQ.addLast(e);
+
+ e = new MonkeyKeyEvent(KeyEvent.ACTION_UP, lastKey);
+ mQ.addLast(e);
+ }
+
+ public boolean validate() {
+ //check factors
+ return adjustEventFactors();
+ }
+
+ public void setVerbose(int verbose) {
+ mVerbose = verbose;
+ }
+
+ /**
+ * generate an activity event
+ */
+ public void generateActivity() {
+ MonkeyActivityEvent e = new MonkeyActivityEvent(mMainApps.get(
+ mRandom.nextInt(mMainApps.size())));
+ mQ.addLast(e);
+ }
+
+ /**
+ * if the queue is empty, we generate events first
+ * @return the first event in the queue
+ */
+ public MonkeyEvent getNextEvent() {
+ if (mQ.isEmpty()) {
+ generateEvents();
+ }
+ mEventCount++;
+ MonkeyEvent e = mQ.getFirst();
+ mQ.removeFirst();
+ return e;
+ }
+}
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceScript.java b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceScript.java
new file mode 100644
index 0000000..aadda9f
--- /dev/null
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceScript.java
@@ -0,0 +1,427 @@
+/*
+ * 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.commands.monkey;
+
+import android.os.SystemClock;
+import android.view.KeyEvent;
+
+import java.io.BufferedReader;
+import java.io.DataInputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.LinkedList;
+import java.util.StringTokenizer;
+
+/**
+ * monkey event queue. It takes a script to produce events
+ *
+ * sample script format:
+ * type= raw events
+ * count= 10
+ * speed= 1.0
+ * captureDispatchPointer(5109520,5109520,0,230.75429,458.1814,0.20784314,
+ * 0.06666667,0,0.0,0.0,65539,0)
+ * captureDispatchKey(5113146,5113146,0,20,0,0,0,0)
+ * captureDispatchFlip(true)
+ * ...
+ */
+public class MonkeySourceScript implements MonkeyEventSource{
+ private int mEventCountInScript = 0; //total number of events in the file
+ private int mVerbose = 0;
+ private double mSpeed = 1.0;
+ private String mScriptFileName;
+ private LinkedList<MonkeyEvent> mQ = new LinkedList<MonkeyEvent>();
+
+ private static final String HEADER_TYPE = "type=";
+ private static final String HEADER_COUNT = "count=";
+ private static final String HEADER_SPEED = "speed=";
+
+ private long mLastRecordedDownTimeKey = 0;
+ private long mLastRecordedDownTimeMotion = 0;
+ private long mLastExportDownTimeKey = 0;
+ private long mLastExportDownTimeMotion = 0;
+ private long mLastExportEventTime = -1;
+ private long mLastRecordedEventTime = -1;
+
+ private static final boolean THIS_DEBUG = false;
+ // a parameter that compensates the difference of real elapsed time and
+ // time in theory
+ private static final long SLEEP_COMPENSATE_DIFF = 16;
+
+ // maximum number of events that we read at one time
+ private static final int MAX_ONE_TIME_READS = 100;
+
+ // number of additional events added to the script
+ // add HOME_KEY down and up events to make start UI consistent in each round
+ private static final int POLICY_ADDITIONAL_EVENT_COUNT = 2;
+
+ // event key word in the capture log
+ private static final String EVENT_KEYWORD_POINTER = "DispatchPointer";
+ private static final String EVENT_KEYWORD_TRACKBALL = "DispatchTrackball";
+ private static final String EVENT_KEYWORD_KEY = "DispatchKey";
+ private static final String EVENT_KEYWORD_FLIP = "DispatchFlip";
+
+ // a line at the end of the header
+ private static final String STARTING_DATA_LINE = "start data >>";
+ private boolean mFileOpened = false;
+ FileInputStream mFStream;
+ DataInputStream mInputStream;
+ BufferedReader mBufferReader;
+
+ public MonkeySourceScript(String filename) {
+ mScriptFileName = filename;
+ }
+
+ /**
+ *
+ * @return the number of total events that will be generated in a round
+ */
+ public int getOneRoundEventCount() {
+ //plus one home key down and up event
+ return mEventCountInScript + POLICY_ADDITIONAL_EVENT_COUNT;
+ }
+
+ private void resetValue() {
+ mLastRecordedDownTimeKey = 0;
+ mLastRecordedDownTimeMotion = 0;
+ mLastExportDownTimeKey = 0;
+ mLastExportDownTimeMotion = 0;
+ mLastRecordedEventTime = -1;
+ mLastExportEventTime = -1;
+ }
+
+ private boolean readScriptHeader() {
+ mEventCountInScript = -1;
+ mFileOpened = false;
+ try {
+ if (THIS_DEBUG) {
+ System.out.println("reading script header");
+ }
+
+ mFStream = new FileInputStream(mScriptFileName);
+ mInputStream = new DataInputStream(mFStream);
+ mBufferReader = new BufferedReader(
+ new InputStreamReader(mInputStream));
+ String sLine;
+ while ((sLine = mBufferReader.readLine()) != null) {
+ sLine = sLine.trim();
+ if (sLine.indexOf(HEADER_TYPE) >= 0) {
+ // at this point, we only have one type of script
+ } else if (sLine.indexOf(HEADER_COUNT) >= 0) {
+ try {
+ mEventCountInScript = Integer.parseInt(sLine.substring(
+ HEADER_COUNT.length() + 1).trim());
+ } catch (NumberFormatException e) {
+ System.err.println(e);
+ }
+ } else if (sLine.indexOf(HEADER_SPEED) >= 0) {
+ try {
+ mSpeed = Double.parseDouble(sLine.substring(
+ HEADER_SPEED.length() + 1).trim());
+
+ } catch (NumberFormatException e) {
+ System.err.println(e);
+ }
+ } else if (sLine.indexOf(STARTING_DATA_LINE) >= 0) {
+ // header ends until we read the start data mark
+ mFileOpened = true;
+ if (THIS_DEBUG) {
+ System.out.println("read script header success");
+ }
+ return true;
+ }
+ }
+ } catch (FileNotFoundException e) {
+ System.err.println(e);
+ } catch (IOException e) {
+ System.err.println(e);
+ }
+
+ if (THIS_DEBUG) {
+ System.out.println("Error in reading script header");
+ }
+ return false;
+ }
+
+ private void processLine(String s) {
+ int index1 = s.indexOf('(');
+ int index2 = s.indexOf(')');
+
+ if (index1 < 0 || index2 < 0) {
+ return;
+ }
+
+ StringTokenizer st = new StringTokenizer(
+ s.substring(index1 + 1, index2), ",");
+
+ if (s.indexOf(EVENT_KEYWORD_KEY) >= 0) {
+ // key events
+ try {
+ long downTime = Long.parseLong(st.nextToken());
+ long eventTime = Long.parseLong(st.nextToken());
+ int action = Integer.parseInt(st.nextToken());
+ int code = Integer.parseInt(st.nextToken());
+ int repeat = Integer.parseInt(st.nextToken());
+ int metaState = Integer.parseInt(st.nextToken());
+ int device = Integer.parseInt(st.nextToken());
+ int scancode = Integer.parseInt(st.nextToken());
+
+ MonkeyKeyEvent e = new MonkeyKeyEvent(downTime, eventTime,
+ action, code, repeat, metaState, device, scancode);
+ mQ.addLast(e);
+
+ } catch (NumberFormatException e) {
+ // something wrong with this line in the script
+ }
+ } else if (s.indexOf(EVENT_KEYWORD_POINTER) >= 0 ||
+ s.indexOf(EVENT_KEYWORD_TRACKBALL) >= 0) {
+ // trackball/pointer event
+ try {
+ long downTime = Long.parseLong(st.nextToken());
+ long eventTime = Long.parseLong(st.nextToken());
+ int action = Integer.parseInt(st.nextToken());
+ float x = Float.parseFloat(st.nextToken());
+ float y = Float.parseFloat(st.nextToken());
+ float pressure = Float.parseFloat(st.nextToken());
+ float size = Float.parseFloat(st.nextToken());
+ int metaState = Integer.parseInt(st.nextToken());
+ float xPrecision = Float.parseFloat(st.nextToken());
+ float yPrecision = Float.parseFloat(st.nextToken());
+ int device = Integer.parseInt(st.nextToken());
+ int edgeFlags = Integer.parseInt(st.nextToken());
+
+ int type = MonkeyEvent.EVENT_TYPE_TRACKBALL;
+ if (s.indexOf("Pointer") > 0) {
+ type = MonkeyEvent.EVENT_TYPE_POINTER;
+ }
+ MonkeyMotionEvent e = new MonkeyMotionEvent(type, downTime, eventTime,
+ action, x, y, pressure, size, metaState, xPrecision, yPrecision,
+ device, edgeFlags);
+ mQ.addLast(e);
+ } catch (NumberFormatException e) {
+ // we ignore this event
+ }
+ } else if (s.indexOf(EVENT_KEYWORD_FLIP) >= 0) {
+ boolean keyboardOpen = Boolean.parseBoolean(st.nextToken());
+ MonkeyFlipEvent e = new MonkeyFlipEvent(keyboardOpen);
+ mQ.addLast(e);
+ }
+ }
+
+ private void closeFile() {
+ mFileOpened = false;
+ if (THIS_DEBUG) {
+ System.out.println("closing script file");
+ }
+
+ try {
+ mFStream.close();
+ mInputStream.close();
+ } catch (IOException e) {
+ System.out.println(e);
+ }
+ }
+
+ /**
+ * add home key press/release event to the queue
+ */
+ private void addHomeKeyEvent() {
+ MonkeyKeyEvent e = new MonkeyKeyEvent(KeyEvent.ACTION_DOWN,
+ KeyEvent.KEYCODE_HOME);
+ mQ.addLast(e);
+ e = new MonkeyKeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HOME);
+ mQ.addLast(e);
+ }
+
+ /**
+ * read next batch of events from the provided script file
+ * @return true if success
+ */
+ private boolean readNextBatch() {
+ String sLine = null;
+ int readCount = 0;
+
+ if (THIS_DEBUG) {
+ System.out.println("readNextBatch(): reading next batch of events");
+ }
+
+ if (!mFileOpened) {
+ if (!readScriptHeader()) {
+ closeFile();
+ return false;
+ }
+ resetValue();
+
+ /*
+ * In order to allow the Monkey to replay captured events multiple times
+ * we need to define a default start UI, which is the home screen
+ * Otherwise, it won't be accurate since the captured events
+ * could end anywhere
+ */
+ addHomeKeyEvent();
+ }
+
+ try {
+ while (readCount++ < MAX_ONE_TIME_READS &&
+ (sLine = mBufferReader.readLine()) != null) {
+ sLine = sLine.trim();
+ processLine(sLine);
+ }
+ } catch (IOException e) {
+ System.err.println(e);
+ return false;
+ }
+
+ if (sLine == null) {
+ // to the end of the file
+ if (THIS_DEBUG) {
+ System.out.println("readNextBatch(): to the end of file");
+ }
+ closeFile();
+ }
+ return true;
+ }
+
+ /**
+ * sleep for a period of given time, introducing latency among events
+ * @param time to sleep in millisecond
+ */
+ private void needSleep(long time) {
+ if (time < 1) {
+ return;
+ }
+ try {
+ Thread.sleep(time);
+ } catch (InterruptedException e) {
+ }
+ }
+
+ /**
+ * check whether we can successfully read the header of the script file
+ */
+ public boolean validate() {
+ boolean b = readNextBatch();
+ if (mVerbose > 0) {
+ System.out.println("Replaying " + mEventCountInScript +
+ " events with speed " + mSpeed);
+ }
+ return b;
+ }
+
+ public void setVerbose(int verbose) {
+ mVerbose = verbose;
+ }
+
+ /**
+ * adjust key downtime and eventtime according to both
+ * recorded values and current system time
+ * @param e KeyEvent
+ */
+ private void adjustKeyEventTime(MonkeyKeyEvent e) {
+ if (e.getEventTime() < 0) {
+ return;
+ }
+ long thisDownTime = 0;
+ long thisEventTime = 0;
+ long expectedDelay = 0;
+
+ if (mLastRecordedEventTime <= 0) {
+ // first time event
+ thisDownTime = SystemClock.uptimeMillis();
+ thisEventTime = thisDownTime;
+ } else {
+ if (e.getDownTime() != mLastRecordedDownTimeKey) {
+ thisDownTime = e.getDownTime();
+ } else {
+ thisDownTime = mLastExportDownTimeKey;
+ }
+ expectedDelay = (long) ((e.getEventTime() -
+ mLastRecordedEventTime) * mSpeed);
+ thisEventTime = mLastExportEventTime + expectedDelay;
+ // add sleep to simulate everything in recording
+ needSleep(expectedDelay - SLEEP_COMPENSATE_DIFF);
+ }
+ mLastRecordedDownTimeKey = e.getDownTime();
+ mLastRecordedEventTime = e.getEventTime();
+ e.setDownTime(thisDownTime);
+ e.setEventTime(thisEventTime);
+ mLastExportDownTimeKey = thisDownTime;
+ mLastExportEventTime = thisEventTime;
+ }
+
+ /**
+ * adjust motion downtime and eventtime according to both
+ * recorded values and current system time
+ * @param e KeyEvent
+ */
+ private void adjustMotionEventTime(MonkeyMotionEvent e) {
+ if (e.getEventTime() < 0) {
+ return;
+ }
+ long thisDownTime = 0;
+ long thisEventTime = 0;
+ long expectedDelay = 0;
+
+ if (mLastRecordedEventTime <= 0) {
+ // first time event
+ thisDownTime = SystemClock.uptimeMillis();
+ thisEventTime = thisDownTime;
+ } else {
+ if (e.getDownTime() != mLastRecordedDownTimeMotion) {
+ thisDownTime = e.getDownTime();
+ } else {
+ thisDownTime = mLastExportDownTimeMotion;
+ }
+ expectedDelay = (long) ((e.getEventTime() -
+ mLastRecordedEventTime) * mSpeed);
+ thisEventTime = mLastExportEventTime + expectedDelay;
+ // add sleep to simulate everything in recording
+ needSleep(expectedDelay - SLEEP_COMPENSATE_DIFF);
+ }
+
+ mLastRecordedDownTimeMotion = e.getDownTime();
+ mLastRecordedEventTime = e.getEventTime();
+ e.setDownTime(thisDownTime);
+ e.setEventTime(thisEventTime);
+ mLastExportDownTimeMotion = thisDownTime;
+ mLastExportEventTime = thisEventTime;
+ }
+
+ /**
+ * if the queue is empty, we generate events first
+ * @return the first event in the queue, if null, indicating the system crashes
+ */
+ public MonkeyEvent getNextEvent() {
+ long recordedEventTime = -1;
+
+ if (mQ.isEmpty()) {
+ readNextBatch();
+ }
+ MonkeyEvent e = mQ.getFirst();
+ mQ.removeFirst();
+
+ if (e.getEventType() == MonkeyEvent.EVENT_TYPE_KEY) {
+ adjustKeyEventTime((MonkeyKeyEvent) e);
+ } else if (e.getEventType() == MonkeyEvent.EVENT_TYPE_POINTER ||
+ e.getEventType() == MonkeyEvent.EVENT_TYPE_TRACKBALL) {
+ adjustMotionEventTime((MonkeyMotionEvent) e);
+ }
+ return e;
+ }
+}
diff --git a/emulator/qemud/qemud.c b/emulator/qemud/qemud.c
index 47d4d5f..3a53716 100644
--- a/emulator/qemud/qemud.c
+++ b/emulator/qemud/qemud.c
@@ -151,7 +151,7 @@
#define xnew0(p) (p) = xalloc0(sizeof(*(p)))
-#define xfree(p) ({ free((p)), (p) = NULL; })
+#define xfree(p) (free((p)), (p) = NULL)
static void*
xrealloc( void* block, size_t size )
@@ -622,13 +622,6 @@
{
int len;
- if (events & (EPOLLHUP|EPOLLERR)) {
- /* disconnection */
- D("%s: disconnect on fd %d", __FUNCTION__, f->fd);
- receiver_close( f->receiver );
- return;
- }
-
if (events & EPOLLIN) {
Packet* p = packet_alloc();
int len;
@@ -643,6 +636,19 @@
}
}
+ /* in certain cases, it's possible to have both EPOLLIN and
+ * EPOLLHUP at the same time. This indicates that there is incoming
+ * data to read, but that the connection was nonetheless closed
+ * by the sender. Be sure to read the data before closing
+ * the receiver to avoid packet loss.
+ */
+ if (events & (EPOLLHUP|EPOLLERR)) {
+ /* disconnection */
+ D("%s: disconnect on fd %d", __FUNCTION__, f->fd);
+ receiver_close( f->receiver );
+ return;
+ }
+
if (events & EPOLLOUT && f->out_first) {
Packet* p = f->out_first;
int avail, len;
@@ -687,13 +693,6 @@
static void
fdhandler_accept_event( FDHandler* f, int events )
{
- if (events & (EPOLLHUP|EPOLLERR)) {
- /* disconnecting !! */
- D("%s: closing fd %d", __FUNCTION__, f->fd);
- receiver_close( f->receiver );
- return;
- }
-
if (events & EPOLLIN) {
/* this is an accept - send a dummy packet to the receiver */
Packet* p = packet_alloc();
@@ -703,6 +702,13 @@
p->len = 1;
receiver_post( f->receiver, p );
}
+
+ if (events & (EPOLLHUP|EPOLLERR)) {
+ /* disconnecting !! */
+ D("%s: closing fd %d", __FUNCTION__, f->fd);
+ receiver_close( f->receiver );
+ return;
+ }
}
@@ -1243,8 +1249,9 @@
#define QEMUD_PREFIX "qemud_"
static const struct { const char* name; ChannelType ctype; } default_channels[] = {
- { "gsm", CHANNEL_DUPLEX }, /* GSM AT command channel, used by commands/rild/rild.c */
- { "gps", CHANNEL_BROADCAST }, /* GPS NMEA commands, used by libs/hardware/qemu_gps.c */
+ { "gsm", CHANNEL_DUPLEX }, /* GSM AT command channel, used by commands/rild/rild.c */
+ { "gps", CHANNEL_BROADCAST }, /* GPS NMEA commands, used by libs/hardware/qemu_gps.c */
+ { "control", CHANNEL_DUPLEX }, /* Used for power/leds/vibrator/etc... */
{ NULL, 0 }
};
diff --git a/ide/eclipse/.classpath b/ide/eclipse/.classpath
index e1a4ff8..0e3f43e 100644
--- a/ide/eclipse/.classpath
+++ b/ide/eclipse/.classpath
@@ -1,56 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
- <classpathentry kind="src" path="java/android"/>
- <classpathentry excluding="android/com/google/tests/|ext/" kind="src" path="java/tests"/>
- <classpathentry kind="lib" path="apps/Calculator/arity-1.3.1.jar"/>
- <classpathentry kind="lib" path="java/ext/googleclient-lib.jar"/>
- <classpathentry kind="lib" path="java/maps/maps-lib.jar"/>
- <classpathentry kind="lib" path="partner/google/apps/Maps/libprotobuffer.jar"/>
- <classpathentry kind="src" path="apps/AlarmClock/src"/>
- <classpathentry kind="src" path="apps/Anagrams/src"/>
- <classpathentry kind="src" path="apps/AndroidTests/DisabledTestApp/src"/>
- <classpathentry kind="src" path="apps/AndroidTests/EnabledTestApp/src"/>
- <classpathentry kind="src" path="apps/AndroidTests/src"/>
- <classpathentry kind="src" path="apps/Browser/src"/>
- <classpathentry kind="src" path="apps/Calculator/src"/>
- <classpathentry kind="src" path="apps/OldCalculator/src"/>
- <classpathentry kind="src" path="apps/Calendar/src"/>
- <classpathentry kind="src" path="apps/Camera/src"/>
- <classpathentry kind="src" path="apps/Contacts/src"/>
- <classpathentry kind="src" path="apps/Fallback/src"/>
- <classpathentry kind="src" path="apps/FontLab/src"/>
- <classpathentry kind="src" path="apps/IM/src"/>
- <classpathentry kind="src" path="apps/Mms/src"/>
- <classpathentry kind="src" path="apps/Music/src"/>
- <classpathentry kind="src" path="apps/PackageInstaller/src"/>
- <classpathentry kind="src" path="apps/Phone/src"/>
- <classpathentry kind="src" path="apps/Quake/src"/>
- <classpathentry kind="src" path="apps/Settings/src"/>
- <classpathentry kind="src" path="apps/SoundRecorder/src"/>
- <classpathentry kind="src" path="apps/StkTest/src"/>
- <classpathentry kind="src" path="apps/Sync/src"/>
- <classpathentry kind="src" path="apps/Term/src"/>
- <classpathentry kind="src" path="apps/TestHarness/src"/>
- <classpathentry kind="src" path="apps/ToDoList/src"/>
- <classpathentry kind="src" path="apps/Updater/src"/>
- <classpathentry kind="src" path="apps/VoiceDialer/src"/>
- <classpathentry kind="src" path="apps/WapBrowser/src"/>
- <classpathentry kind="src" path="apps/WhackAMole/src"/>
- <classpathentry kind="src" path="commands/am/src"/>
- <classpathentry kind="src" path="commands/input/src"/>
- <classpathentry kind="src" path="commands/monkey/src"/>
- <classpathentry kind="src" path="commands/pm/src"/>
- <classpathentry kind="src" path="content/providers/calendar/src"/>
- <classpathentry kind="src" path="content/providers/contacts/src"/>
- <classpathentry kind="src" path="content/providers/downloads/src"/>
- <classpathentry kind="src" path="content/providers/drm/src"/>
- <classpathentry kind="src" path="content/providers/im/src"/>
- <classpathentry kind="src" path="content/providers/media/src"/>
- <classpathentry kind="src" path="content/providers/settings/src"/>
- <classpathentry kind="src" path="content/providers/subscribedfeeds/src"/>
- <classpathentry kind="src" path="content/providers/sync/src"/>
- <classpathentry kind="src" path="content/providers/telephony/src"/>
- <classpathentry kind="src" path="content/tests/providers/contacts/src"/>
+ <classpathentry kind="src" path="packages/apps/AlarmClock/src"/>
+ <classpathentry kind="src" path="packages/apps/Browser/src"/>
+ <classpathentry kind="src" path="packages/apps/Calendar/src"/>
+ <classpathentry kind="src" path="packages/apps/Calculator/src"/>
+ <classpathentry kind="src" path="packages/apps/Camera/src"/>
+ <classpathentry kind="src" path="packages/apps/Contacts/src"/>
+ <classpathentry kind="src" path="packages/apps/Email/src"/>
+ <classpathentry kind="src" path="packages/apps/GoogleSearch/src"/>
+ <classpathentry kind="src" path="packages/apps/HTMLViewer/src"/>
+ <classpathentry kind="src" path="packages/apps/IM/src"/>
+ <classpathentry kind="src" path="packages/apps/IM/plugin"/>
+ <classpathentry kind="src" path="packages/apps/Launcher/src"/>
+ <classpathentry kind="src" path="packages/apps/Music/src"/>
+ <classpathentry kind="src" path="packages/apps/Mms/src"/>
+ <classpathentry kind="src" path="packages/apps/PackageInstaller/src"/>
+ <classpathentry kind="src" path="packages/apps/Phone/src"/>
+ <classpathentry kind="src" path="packages/apps/Settings/src"/>
+ <classpathentry kind="src" path="packages/apps/SoundRecorder/src"/>
+ <classpathentry kind="src" path="packages/apps/Stk/src"/>
+ <classpathentry kind="src" path="packages/apps/Sync/src"/>
+ <classpathentry kind="src" path="packages/apps/Updater/src"/>
+ <classpathentry kind="src" path="packages/apps/VoiceDialer/src"/>
+ <classpathentry kind="src" path="packages/providers/CalendarProvider/src"/>
+ <classpathentry kind="src" path="packages/providers/ContactsProvider/src"/>
+ <classpathentry kind="src" path="packages/providers/DownloadProvider/src"/>
+ <classpathentry kind="src" path="packages/providers/DrmProvider/src"/>
+ <classpathentry kind="src" path="packages/providers/ImProvider/src"/>
+ <classpathentry kind="src" path="packages/providers/MediaProvider/src"/>
+ <classpathentry kind="src" path="packages/providers/TelephonyProvider/src"/>
+ <classpathentry kind="src" path="vendor/google/apps/Street/src"/>
+ <classpathentry kind="src" path="vendor/google/apps/YouTube/src"/>
+ <classpathentry kind="src" path="frameworks/base/awt"/>
+ <classpathentry kind="src" path="frameworks/base/cmds/am/src"/>
+ <classpathentry kind="src" path="frameworks/base/cmds/input/src"/>
+ <classpathentry kind="src" path="frameworks/base/cmds/pm/src"/>
+ <classpathentry kind="src" path="frameworks/base/cmds/svc/src"/>
+ <classpathentry kind="src" path="frameworks/base/core/java"/>
+ <classpathentry kind="src" path="frameworks/base/graphics/java"/>
+ <classpathentry kind="src" path="frameworks/base/im/java"/>
+ <classpathentry kind="src" path="frameworks/base/location/java"/>
+ <classpathentry kind="src" path="frameworks/base/media/java"/>
+ <classpathentry kind="src" path="frameworks/base/opengl/java"/>
+ <classpathentry kind="src" path="frameworks/base/packages/SettingsProvider/src"/>
+ <classpathentry kind="src" path="frameworks/base/packages/SubscribedFeedsProvider/src"/>
+ <classpathentry kind="src" path="frameworks/base/sax/java"/>
+ <classpathentry kind="src" path="frameworks/base/services/java"/>
+ <classpathentry kind="src" path="frameworks/base/telephony/java"/>
+ <classpathentry kind="src" path="frameworks/base/test-runner"/>
+ <classpathentry kind="src" path="frameworks/base/wifi/java"/>
+ <classpathentry kind="src" path="frameworks/policies/base/phone"/>
+ <classpathentry kind="src" path="development/samples/ApiDemos/src"/>
+ <classpathentry kind="src" path="development/samples/ApiDemos/tests/src"/>
+ <classpathentry kind="src" path="development/samples/Compass/src"/>
+ <classpathentry kind="src" path="development/samples/HelloActivity/src"/>
+ <classpathentry kind="src" path="development/samples/HelloActivity/tests/src"/>
+ <classpathentry kind="src" path="development/samples/Home/src"/>
+ <classpathentry kind="src" path="development/samples/LunarLander/src"/>
+ <classpathentry kind="src" path="development/samples/LunarLander/tests/src"/>
+ <classpathentry kind="src" path="development/samples/NotePad/src"/>
+ <classpathentry kind="src" path="development/samples/NotePad/tests/src"/>
+ <classpathentry kind="src" path="development/samples/RSSReader/src"/>
+ <classpathentry kind="src" path="development/samples/SkeletonApp/src"/>
+ <classpathentry kind="src" path="development/samples/SkeletonApp/tests/src"/>
+ <classpathentry kind="src" path="development/samples/Snake/src"/>
+ <classpathentry kind="src" path="development/samples/Snake/tests/src"/>
<classpathentry kind="src" path="dalvik/libcore/annotation/src/main/java"/>
<classpathentry kind="src" path="dalvik/libcore/archive/src/main/java"/>
<classpathentry kind="src" path="dalvik/libcore/auth/src/main/java"/>
@@ -59,77 +73,44 @@
<classpathentry kind="src" path="dalvik/libcore/crypto/src/main/java"/>
<classpathentry kind="src" path="dalvik/libcore/dalvik/src/main/java"/>
<classpathentry kind="src" path="dalvik/libcore/icu/src/main/java"/>
- <classpathentry kind="src" path="dalvik/libcore/instrument/src/main/java"/>
<classpathentry kind="src" path="dalvik/libcore/json/src/main/java"/>
<classpathentry kind="src" path="dalvik/libcore/junit/src/main/java"/>
<classpathentry kind="src" path="dalvik/libcore/logging/src/main/java"/>
<classpathentry kind="src" path="dalvik/libcore/luni-kernel/src/main/java"/>
<classpathentry kind="src" path="dalvik/libcore/luni/src/main/java"/>
<classpathentry kind="src" path="dalvik/libcore/math/src/main/java"/>
- <classpathentry kind="src" path="dalvik/libcore/nio/src/main/java"/>
<classpathentry kind="src" path="dalvik/libcore/nio_char/src/main/java"/>
+ <classpathentry kind="src" path="dalvik/libcore/nio/src/main/java"/>
<classpathentry kind="src" path="dalvik/libcore/openssl/src/main/java"/>
<classpathentry kind="src" path="dalvik/libcore/prefs/src/main/java"/>
<classpathentry kind="src" path="dalvik/libcore/regex/src/main/java"/>
<classpathentry kind="src" path="dalvik/libcore/security-kernel/src/main/java"/>
<classpathentry kind="src" path="dalvik/libcore/security/src/main/java"/>
- <classpathentry kind="src" path="dalvik/libcore/sound/src/main/java"/>
<classpathentry kind="src" path="dalvik/libcore/sql/src/main/java"/>
<classpathentry kind="src" path="dalvik/libcore/suncompat/src/main/java"/>
<classpathentry kind="src" path="dalvik/libcore/text/src/main/java"/>
<classpathentry kind="src" path="dalvik/libcore/x-net/src/main/java"/>
<classpathentry kind="src" path="dalvik/libcore/xml/src/main/java"/>
- <classpathentry kind="src" path="java/config/release"/>
- <classpathentry kind="src" path="java/ext"/>
- <classpathentry kind="src" path="java/gtalkservice"/>
- <classpathentry kind="src" path="java/maps"/>
- <classpathentry kind="src" path="java/policy/phone"/>
- <classpathentry kind="src" path="java/services"/>
- <classpathentry kind="src" path="java/tests/ext"/>
- <classpathentry kind="src" path="java/test-runner"/>
- <classpathentry kind="src" path="out/target/common/R"/>
- <classpathentry kind="src" path="out/target/common/obj/APPS/AndroidTests_intermediates/src/src"/>
<classpathentry kind="src" path="out/target/common/obj/APPS/ApiDemos_intermediates/src/src"/>
<classpathentry kind="src" path="out/target/common/obj/APPS/Browser_intermediates/src/src"/>
- <classpathentry kind="src" path="out/target/common/obj/APPS/Development_intermediates/src/src"/>
<classpathentry kind="src" path="out/target/common/obj/APPS/IM_intermediates/src/src"/>
<classpathentry kind="src" path="out/target/common/obj/APPS/Music_intermediates/src/src"/>
<classpathentry kind="src" path="out/target/common/obj/APPS/Phone_intermediates/src/src"/>
- <classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src"/>
- <classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/com.google.android.gtalkservice_intermediates/src"/>
- <classpathentry kind="src" path="partner/google/apps/Cocktail/src"/>
- <classpathentry kind="src" path="partner/google/apps/GTalkService/src"/>
- <classpathentry kind="src" path="partner/google/apps/Gadgets/src"/>
- <classpathentry kind="src" path="partner/google/apps/Gmail/src"/>
- <classpathentry kind="src" path="partner/google/apps/GoogleApps/src"/>
- <classpathentry kind="src" path="partner/google/apps/Home/src"/>
- <classpathentry kind="src" path="partner/google/apps/Maps/src"/>
- <classpathentry kind="src" path="partner/google/apps/SetupWizard/src"/>
- <classpathentry kind="src" path="partner/google/apps/Street/src"/>
- <classpathentry kind="src" path="partner/google/apps/Talk/src"/>
- <classpathentry kind="src" path="partner/google/apps/Vending/src"/>
- <classpathentry kind="src" path="partner/google/apps/YouTube/src"/>
- <classpathentry kind="src" path="partner/google/providers/gmail/src"/>
- <classpathentry kind="src" path="partner/google/tests/GmailProvider/src"/>
- <classpathentry kind="src" path="partner/google/tests/GoogleApps/src"/>
- <classpathentry kind="src" path="partner/google/tests/Maps/src"/>
- <classpathentry kind="src" path="partner/google/tests/WeiTest/src"/>
- <classpathentry kind="src" path="partner/tmobile/apps/MyFaves/src"/>
- <classpathentry kind="src" path="partner/tmobile/tests/CarrierDiagnostics/src"/>
- <classpathentry kind="src" path="samples/ApiDemos/src"/>
- <classpathentry kind="src" path="samples/HelloActivity/src"/>
- <classpathentry kind="src" path="samples/ImageCaption/src"/>
- <classpathentry kind="src" path="samples/LunarLander/src"/>
- <classpathentry kind="src" path="samples/NotePad/src"/>
- <classpathentry kind="src" path="samples/RSSReader/src"/>
- <classpathentry kind="src" path="samples/SkeletonApp/src"/>
- <classpathentry kind="src" path="samples/Snake/src"/>
- <classpathentry kind="src" path="tests/Dashboard/src"/>
- <classpathentry kind="src" path="tests/DataSets/src"/>
- <classpathentry kind="src" path="tests/Development/src"/>
- <classpathentry kind="src" path="tests/DumpRenderTree/src"/>
- <classpathentry kind="src" path="tests/FrameworkTests/src"/>
- <classpathentry kind="src" path="tests/FrameworkTests/tests/src"/>
- <classpathentry kind="src" path="tests/framework-tests/src"/>
- <classpathentry kind="output" path="out/eclipse"/>
+ <classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/com.android.im.plugin_intermediates/src"/>
+ <classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java"/>
+ <classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/im/java"/>
+ <classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/location/java"/>
+ <classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/media/java"/>
+ <classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/telephony/java"/>
+ <classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/wifi/java"/>
+ <classpathentry kind="src" path="out/target/common/R"/>
+ <classpathentry kind="src" path="external/tagsoup/src"/>
+ <classpathentry kind="src" path="external/protobuf/src"/>
+ <classpathentry kind="src" path="external/gdata/src"/>
+ <classpathentry kind="src" path="external/apache-http/src"/>
+ <classpathentry kind="lib" path="external/googleclient/googleclient-lib.jar"/>
+ <classpathentry kind="lib" path="out/target/common/obj/JAVA_LIBRARIES/google-framework_intermediates/javalib.jar"/>
+ <classpathentry kind="lib" path="out/target/common/obj/JAVA_LIBRARIES/googlelogin-client_intermediates/javalib.jar"/>
+ <classpathentry kind="lib" path="packages/apps/Calculator/arity-1.3.1.jar"/>
+ <classpathentry kind="output" path="out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/classes"/>
</classpath>
diff --git a/ide/xcode/SampleCode/SampleCode.xcodeproj/project.pbxproj b/ide/xcode/SampleCode/SampleCode.xcodeproj/project.pbxproj
index 22629d0..826bb6a 100644
--- a/ide/xcode/SampleCode/SampleCode.xcodeproj/project.pbxproj
+++ b/ide/xcode/SampleCode/SampleCode.xcodeproj/project.pbxproj
@@ -7,23 +7,38 @@
objects = {
/* Begin PBXBuildFile section */
+ 0007A8F30DB4DFF30068AF40 /* SampleXfermodes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0007A8F20DB4DFF30068AF40 /* SampleXfermodes.cpp */; };
0008AEE10DABF08F00477EFB /* libgiflib.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0008AEDE0DABF01400477EFB /* libgiflib.a */; };
000A1CB00DA522ED003DAC04 /* SamplePolyToPoly.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 000A1CAF0DA522ED003DAC04 /* SamplePolyToPoly.cpp */; };
000DC0C60D63796E00854F5A /* SampleTextAlpha.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 000DC0C50D63796E00854F5A /* SampleTextAlpha.cpp */; };
+ 001142AB0DCA20650070D0A3 /* SamplePicture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 001142AA0DCA20650070D0A3 /* SamplePicture.cpp */; };
0017F1490D6A0A6A008D9B31 /* SampleEmboss.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0017F1460D6A0A6A008D9B31 /* SampleEmboss.cpp */; };
0017F14A0D6A0A6A008D9B31 /* SampleLines.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0017F1470D6A0A6A008D9B31 /* SampleLines.cpp */; };
- 0017F14B0D6A0A6A008D9B31 /* SamplePatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0017F1480D6A0A6A008D9B31 /* SamplePatch.cpp */; };
0017F2CF0D6F3933008D9B31 /* libgraphics.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00ED8C440D3E999300651393 /* libgraphics.a */; };
0017F2D00D6F393F008D9B31 /* libcorecg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00ED8C2C0D3E999300651393 /* libcorecg.a */; };
0017F2D60D6F3949008D9B31 /* libviews.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00ED8C5E0D3E999300651393 /* libviews.a */; };
+ 0019628A0EACB9D300447A07 /* SamplePatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 001962890EACB9D300447A07 /* SamplePatch.cpp */; };
+ 001962900EACBA2A00447A07 /* SamplePageFlip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0019628F0EACBA2A00447A07 /* SamplePageFlip.cpp */; };
+ 002919440DEBA08100AF67D5 /* SkBitmapFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 002919430DEBA08100AF67D5 /* SkBitmapFilter.cpp */; };
+ 002919510DEC39C700AF67D5 /* SkConvolutionBitmapFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 002919500DEC39C700AF67D5 /* SkConvolutionBitmapFilter.cpp */; };
+ 00298C2A0E7085E7005E85ED /* SampleStrokeText.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00298C290E7085E7005E85ED /* SampleStrokeText.cpp */; };
003474ED0D5B61BA00F3F389 /* SampleVertices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 003474EC0D5B61BA00F3F389 /* SampleVertices.cpp */; };
+ 003476840DF8DEC400A270A4 /* SampleCircle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 003476830DF8DEC400A270A4 /* SampleCircle.cpp */; };
+ 003A10170E0C29F800136848 /* SampleOverflow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 003A10160E0C29F800136848 /* SampleOverflow.cpp */; };
003FA70A0D58CA4D0063AD75 /* SampleMeasure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 003FA7090D58CA4D0063AD75 /* SampleMeasure.cpp */; };
+ 0061A77B0DB7A7150007094E /* SampleFillType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0061A77A0DB7A7150007094E /* SampleFillType.cpp */; };
+ 00648B5A0DDB15B90087F2E8 /* SampleTypeface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00648B590DDB15B90087F2E8 /* SampleTypeface.cpp */; };
00685FCE0D8A16C300CD71AA /* SampleAll.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00ED8C650D3E99A800651393 /* SampleAll.cpp */; };
006860100D8A1C8B00CD71AA /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0068600F0D8A1C8A00CD71AA /* OpenGL.framework */; };
006860290D8A1DFB00CD71AA /* AGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 006860280D8A1DFB00CD71AA /* AGL.framework */; };
0071BCEF0D746BDF00F667CE /* SampleFilter2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0071BCEE0D746BDF00F667CE /* SampleFilter2.cpp */; };
- 007ECA770DA684A90086775A /* libpvjpeg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 007ECA760DA684A20086775A /* libpvjpeg.a */; };
009A74250DA11C5D00876C03 /* libGL.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 009A740E0DA11B1F00876C03 /* libGL.a */; };
+ 00B8EBFC0EB64ABC003C2F6F /* SampleDrawLooper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00B8EBFB0EB64ABC003C2F6F /* SampleDrawLooper.cpp */; };
+ 00C5D1E10EBFFE4D00C6702C /* test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00C5D1E00EBFFE4D00C6702C /* test.cpp */; };
+ 00C5D1E50EC0007400C6702C /* test_drawcolor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00C5D1E40EC0007400C6702C /* test_drawcolor.cpp */; };
+ 00C5D2010EC00F0300C6702C /* SampleTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00C5D2000EC00F0300C6702C /* SampleTests.cpp */; };
+ 00C5D20E0EC0106F00C6702C /* test_drawrect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00C5D1F00EC0044600C6702C /* test_drawrect.cpp */; };
+ 00D12E4D0DAD3D0A003918C5 /* libanimator.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0013C7920D94043200B41703 /* libanimator.a */; };
00D315710D5A5B1D004B2209 /* SampleBitmapRect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00D315700D5A5B1D004B2209 /* SampleBitmapRect.cpp */; };
00ED8C7C0D3E99A800651393 /* SampleApp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00ED8C660D3E99A800651393 /* SampleApp.cpp */; };
00ED8C7D0D3E99A800651393 /* SampleArc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00ED8C670D3E99A800651393 /* SampleArc.cpp */; };
@@ -52,6 +67,7 @@
00ED8CDD0D3E9FE700651393 /* libports-mac.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00ED8C520D3E999300651393 /* libports-mac.a */; };
00ED8CDE0D3E9FEA00651393 /* libports.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00ED8C580D3E999300651393 /* libports.a */; };
00ED8CE00D3E9FEF00651393 /* libzlib.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00ED8C620D3E999300651393 /* libzlib.a */; };
+ 00F9D6860E7F51680031AAA2 /* SkSetPoly3To3_A.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00F9D6850E7F51670031AAA2 /* SkSetPoly3To3_A.cpp */; };
8D0C4E8D0486CD37000505A6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0867D6AAFE840B52C02AAC07 /* InfoPlist.strings */; };
8D0C4E8E0486CD37000505A6 /* main.nib in Resources */ = {isa = PBXBuildFile; fileRef = 02345980000FD03B11CA0E72 /* main.nib */; };
8D0C4E920486CD37000505A6 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20286C33FDCF999611CA2CEA /* Carbon.framework */; };
@@ -62,14 +78,14 @@
isa = PBXContainerItemProxy;
containerPortal = 0008AED90DABF01300477EFB /* giflib.xcodeproj */;
proxyType = 2;
- remoteGlobalIDString = D2AAC046055464E500DB518D /* libgiflib.a */;
+ remoteGlobalIDString = D2AAC046055464E500DB518D;
remoteInfo = giflib;
};
0008AF0F0DABF9BD00477EFB /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0008AED90DABF01300477EFB /* giflib.xcodeproj */;
proxyType = 1;
- remoteGlobalIDString = D2AAC045055464E500DB518D /* giflib */;
+ remoteGlobalIDString = D2AAC045055464E500DB518D;
remoteInfo = giflib;
};
0013C7910D94043200B41703 /* PBXContainerItemProxy */ = {
@@ -86,20 +102,6 @@
remoteGlobalIDString = D2AAC045055464E500DB518D;
remoteInfo = animator;
};
- 007ECA750DA684A20086775A /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 007ECA710DA684A20086775A /* pvjpeg.xcodeproj */;
- proxyType = 2;
- remoteGlobalIDString = D2AAC046055464E500DB518D;
- remoteInfo = pvjpeg;
- };
- 007ECA7B0DA684CF0086775A /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 007ECA710DA684A20086775A /* pvjpeg.xcodeproj */;
- proxyType = 1;
- remoteGlobalIDString = D2AAC045055464E500DB518D;
- remoteInfo = pvjpeg;
- };
009A740D0DA11B1F00876C03 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 009A74060DA11B1F00876C03 /* GL.xcodeproj */;
@@ -257,22 +259,42 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
+ 0007A8F20DB4DFF30068AF40 /* SampleXfermodes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleXfermodes.cpp; path = ../../../tests/skia/SampleCode/SampleXfermodes.cpp; sourceTree = SOURCE_ROOT; };
0008AED90DABF01300477EFB /* giflib.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = giflib.xcodeproj; path = ../giflib.xcodeproj; sourceTree = SOURCE_ROOT; };
000A1CAF0DA522ED003DAC04 /* SamplePolyToPoly.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SamplePolyToPoly.cpp; path = ../../../tests/skia/SampleCode/SamplePolyToPoly.cpp; sourceTree = SOURCE_ROOT; };
000DC0C50D63796E00854F5A /* SampleTextAlpha.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleTextAlpha.cpp; path = ../../../tests/skia/SampleCode/SampleTextAlpha.cpp; sourceTree = SOURCE_ROOT; };
+ 001142AA0DCA20650070D0A3 /* SamplePicture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SamplePicture.cpp; path = ../../../tests/skia/SampleCode/SamplePicture.cpp; sourceTree = SOURCE_ROOT; };
0013C78A0D94043200B41703 /* animator.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = animator.xcodeproj; path = ../animator.xcodeproj; sourceTree = SOURCE_ROOT; };
0017F1460D6A0A6A008D9B31 /* SampleEmboss.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleEmboss.cpp; path = ../../../tests/skia/SampleCode/SampleEmboss.cpp; sourceTree = SOURCE_ROOT; };
0017F1470D6A0A6A008D9B31 /* SampleLines.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleLines.cpp; path = ../../../tests/skia/SampleCode/SampleLines.cpp; sourceTree = SOURCE_ROOT; };
- 0017F1480D6A0A6A008D9B31 /* SamplePatch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SamplePatch.cpp; path = ../../../tests/skia/SampleCode/SamplePatch.cpp; sourceTree = SOURCE_ROOT; };
0017F1510D6A0A8A008D9B31 /* SkGeometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SkGeometry.h; path = ../../../libs/graphics/sgl/SkGeometry.h; sourceTree = SOURCE_ROOT; };
+ 001962890EACB9D300447A07 /* SamplePatch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SamplePatch.cpp; path = ../../../tests/skia/SampleCode/SamplePatch.cpp; sourceTree = SOURCE_ROOT; };
+ 0019628F0EACBA2A00447A07 /* SamplePageFlip.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SamplePageFlip.cpp; path = ../../../tests/skia/SampleCode/SamplePageFlip.cpp; sourceTree = SOURCE_ROOT; };
+ 002919430DEBA08100AF67D5 /* SkBitmapFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkBitmapFilter.cpp; path = ../../../libs/graphics/sgl/SkBitmapFilter.cpp; sourceTree = SOURCE_ROOT; };
+ 002919500DEC39C700AF67D5 /* SkConvolutionBitmapFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkConvolutionBitmapFilter.cpp; path = ../../../libs/graphics/effects/SkConvolutionBitmapFilter.cpp; sourceTree = SOURCE_ROOT; };
+ 00298C290E7085E7005E85ED /* SampleStrokeText.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleStrokeText.cpp; path = ../../../tests/skia/SampleCode/SampleStrokeText.cpp; sourceTree = SOURCE_ROOT; };
003474EC0D5B61BA00F3F389 /* SampleVertices.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleVertices.cpp; path = ../../../tests/skia/SampleCode/SampleVertices.cpp; sourceTree = SOURCE_ROOT; };
+ 003476830DF8DEC400A270A4 /* SampleCircle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleCircle.cpp; path = ../../../tests/skia/SampleCode/SampleCircle.cpp; sourceTree = SOURCE_ROOT; };
+ 003A10160E0C29F800136848 /* SampleOverflow.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleOverflow.cpp; path = ../../../tests/skia/SampleCode/SampleOverflow.cpp; sourceTree = SOURCE_ROOT; };
003FA7090D58CA4D0063AD75 /* SampleMeasure.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleMeasure.cpp; path = ../../../tests/skia/SampleCode/SampleMeasure.cpp; sourceTree = SOURCE_ROOT; };
+ 0041F4860DE1157900C74590 /* SkFontHost_FONTPATH.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkFontHost_FONTPATH.cpp; path = ../../../libs/graphics/ports/SkFontHost_FONTPATH.cpp; sourceTree = SOURCE_ROOT; };
+ 0041F4870DE1157900C74590 /* SkFontHost_none.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkFontHost_none.cpp; path = ../../../libs/graphics/ports/SkFontHost_none.cpp; sourceTree = SOURCE_ROOT; };
+ 0041F4880DE1157900C74590 /* SkFontHost_win.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkFontHost_win.cpp; path = ../../../libs/graphics/ports/SkFontHost_win.cpp; sourceTree = SOURCE_ROOT; };
+ 0061A77A0DB7A7150007094E /* SampleFillType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleFillType.cpp; path = ../../../tests/skia/SampleCode/SampleFillType.cpp; sourceTree = SOURCE_ROOT; };
+ 00648B590DDB15B90087F2E8 /* SampleTypeface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleTypeface.cpp; path = ../../../tests/skia/SampleCode/SampleTypeface.cpp; sourceTree = SOURCE_ROOT; };
0068600F0D8A1C8A00CD71AA /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = SDKs/MacOSX10.5.sdk/System/Library/Frameworks/OpenGL.framework; sourceTree = DEVELOPER_DIR; };
006860280D8A1DFB00CD71AA /* AGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AGL.framework; path = SDKs/MacOSX10.5.sdk/System/Library/Frameworks/AGL.framework; sourceTree = DEVELOPER_DIR; };
0071BCEE0D746BDF00F667CE /* SampleFilter2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleFilter2.cpp; path = ../../../tests/skia/SampleCode/SampleFilter2.cpp; sourceTree = SOURCE_ROOT; };
- 007ECA710DA684A20086775A /* pvjpeg.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = pvjpeg.xcodeproj; path = ../pvjpeg.xcodeproj; sourceTree = SOURCE_ROOT; };
009A74060DA11B1F00876C03 /* GL.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GL.xcodeproj; path = ../GL.xcodeproj; sourceTree = SOURCE_ROOT; };
+ 00B8EBDF0EB63983003C2F6F /* SkLayerDrawLooper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkLayerDrawLooper.cpp; path = ../../../libs/graphics/effects/SkLayerDrawLooper.cpp; sourceTree = SOURCE_ROOT; };
+ 00B8EBFB0EB64ABC003C2F6F /* SampleDrawLooper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleDrawLooper.cpp; path = ../../../tests/skia/SampleCode/SampleDrawLooper.cpp; sourceTree = SOURCE_ROOT; };
+ 00C5D1DD0EBFFC5C00C6702C /* test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = test.h; path = ../../../tests/skia/test/test.h; sourceTree = SOURCE_ROOT; };
+ 00C5D1E00EBFFE4D00C6702C /* test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = test.cpp; path = ../../../tests/skia/test/test.cpp; sourceTree = SOURCE_ROOT; };
+ 00C5D1E40EC0007400C6702C /* test_drawcolor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = test_drawcolor.cpp; path = ../../../tests/skia/test/test_drawcolor.cpp; sourceTree = SOURCE_ROOT; };
+ 00C5D1F00EC0044600C6702C /* test_drawrect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = test_drawrect.cpp; path = ../../../tests/skia/test/test_drawrect.cpp; sourceTree = SOURCE_ROOT; };
+ 00C5D2000EC00F0300C6702C /* SampleTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleTests.cpp; path = ../../../tests/skia/SampleCode/SampleTests.cpp; sourceTree = SOURCE_ROOT; };
00D315700D5A5B1D004B2209 /* SampleBitmapRect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleBitmapRect.cpp; path = ../../../tests/skia/SampleCode/SampleBitmapRect.cpp; sourceTree = SOURCE_ROOT; };
+ 00DB0B0D0E06CEC80061DE48 /* SampleNinePatch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleNinePatch.cpp; path = ../../../tests/skia/SampleCode/SampleNinePatch.cpp; sourceTree = SOURCE_ROOT; };
00ED8C060D3E999300651393 /* corecg.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = corecg.xcodeproj; path = ../corecg.xcodeproj; sourceTree = SOURCE_ROOT; };
00ED8C090D3E999300651393 /* expat.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = expat.xcodeproj; path = ../expat.xcodeproj; sourceTree = SOURCE_ROOT; };
00ED8C0C0D3E999300651393 /* freetype2.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = freetype2.xcodeproj; path = ../freetype2.xcodeproj; sourceTree = SOURCE_ROOT; };
@@ -305,6 +327,9 @@
00ED8C780D3E99A800651393 /* SampleTextEffects.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleTextEffects.cpp; path = ../../../tests/skia/SampleCode/SampleTextEffects.cpp; sourceTree = SOURCE_ROOT; };
00ED8C790D3E99A800651393 /* SampleTextOnPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleTextOnPath.cpp; path = ../../../tests/skia/SampleCode/SampleTextOnPath.cpp; sourceTree = SOURCE_ROOT; };
00ED8C7A0D3E99A800651393 /* SampleTiling.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleTiling.cpp; path = ../../../tests/skia/SampleCode/SampleTiling.cpp; sourceTree = SOURCE_ROOT; };
+ 00F9D6230E7EC9E60031AAA2 /* SkSetPoly3To3.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkSetPoly3To3.cpp; path = ../../../libs/corecg/SkSetPoly3To3.cpp; sourceTree = SOURCE_ROOT; };
+ 00F9D6540E7EEE580031AAA2 /* SkSetPoly3To3_D.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkSetPoly3To3_D.cpp; path = ../../../libs/corecg/SkSetPoly3To3_D.cpp; sourceTree = SOURCE_ROOT; };
+ 00F9D6850E7F51670031AAA2 /* SkSetPoly3To3_A.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkSetPoly3To3_A.cpp; path = ../../../libs/corecg/SkSetPoly3To3_A.cpp; sourceTree = SOURCE_ROOT; };
0867D6ABFE840B52C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
1870340FFE93FCAF11CA0CD7 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/main.nib; sourceTree = "<group>"; };
20286C33FDCF999611CA2CEA /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
@@ -331,8 +356,8 @@
006860100D8A1C8B00CD71AA /* OpenGL.framework in Frameworks */,
006860290D8A1DFB00CD71AA /* AGL.framework in Frameworks */,
009A74250DA11C5D00876C03 /* libGL.a in Frameworks */,
- 007ECA770DA684A90086775A /* libpvjpeg.a in Frameworks */,
0008AEE10DABF08F00477EFB /* libgiflib.a in Frameworks */,
+ 00D12E4D0DAD3D0A003918C5 /* libanimator.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -355,12 +380,14 @@
name = Products;
sourceTree = "<group>";
};
- 007ECA720DA684A20086775A /* Products */ = {
+ 0041F4850DE1154C00C74590 /* fonthosts */ = {
isa = PBXGroup;
children = (
- 007ECA760DA684A20086775A /* libpvjpeg.a */,
+ 0041F4860DE1157900C74590 /* SkFontHost_FONTPATH.cpp */,
+ 0041F4870DE1157900C74590 /* SkFontHost_none.cpp */,
+ 0041F4880DE1157900C74590 /* SkFontHost_win.cpp */,
);
- name = Products;
+ name = fonthosts;
sourceTree = "<group>";
};
009A74070DA11B1F00876C03 /* Products */ = {
@@ -371,6 +398,17 @@
name = Products;
sourceTree = "<group>";
};
+ 00C5D1DB0EBFF83100C6702C /* tests */ = {
+ isa = PBXGroup;
+ children = (
+ 00C5D1E00EBFFE4D00C6702C /* test.cpp */,
+ 00C5D1F00EC0044600C6702C /* test_drawrect.cpp */,
+ 00C5D1E40EC0007400C6702C /* test_drawcolor.cpp */,
+ 00C5D1DD0EBFFC5C00C6702C /* test.h */,
+ );
+ name = tests;
+ sourceTree = "<group>";
+ };
00ED8C070D3E999300651393 /* Products */ = {
isa = PBXGroup;
children = (
@@ -462,8 +500,15 @@
20286C29FDCF999611CA2CEA /* SampleCode */ = {
isa = PBXGroup;
children = (
+ 00C5D1DB0EBFF83100C6702C /* tests */,
+ 00F9D6230E7EC9E60031AAA2 /* SkSetPoly3To3.cpp */,
+ 00B8EBDF0EB63983003C2F6F /* SkLayerDrawLooper.cpp */,
+ 00F9D6850E7F51670031AAA2 /* SkSetPoly3To3_A.cpp */,
+ 00F9D6540E7EEE580031AAA2 /* SkSetPoly3To3_D.cpp */,
+ 002919500DEC39C700AF67D5 /* SkConvolutionBitmapFilter.cpp */,
+ 002919430DEBA08100AF67D5 /* SkBitmapFilter.cpp */,
+ 0041F4850DE1154C00C74590 /* fonthosts */,
0008AED90DABF01300477EFB /* giflib.xcodeproj */,
- 007ECA710DA684A20086775A /* pvjpeg.xcodeproj */,
009A74060DA11B1F00876C03 /* GL.xcodeproj */,
0013C78A0D94043200B41703 /* animator.xcodeproj */,
00ED8C060D3E999300651393 /* corecg.xcodeproj */,
@@ -487,22 +532,29 @@
20286C2AFDCF999611CA2CEA /* Sources */ = {
isa = PBXGroup;
children = (
+ 001962890EACB9D300447A07 /* SamplePatch.cpp */,
+ 00298C290E7085E7005E85ED /* SampleStrokeText.cpp */,
+ 001142AA0DCA20650070D0A3 /* SamplePicture.cpp */,
+ 0007A8F20DB4DFF30068AF40 /* SampleXfermodes.cpp */,
000A1CAF0DA522ED003DAC04 /* SamplePolyToPoly.cpp */,
0017F1510D6A0A8A008D9B31 /* SkGeometry.h */,
0017F1460D6A0A6A008D9B31 /* SampleEmboss.cpp */,
0017F1470D6A0A6A008D9B31 /* SampleLines.cpp */,
- 0017F1480D6A0A6A008D9B31 /* SamplePatch.cpp */,
00ED8C650D3E99A800651393 /* SampleAll.cpp */,
00ED8C660D3E99A800651393 /* SampleApp.cpp */,
00ED8C670D3E99A800651393 /* SampleArc.cpp */,
00ED8C680D3E99A800651393 /* SampleCamera.cpp */,
00ED8C690D3E99A800651393 /* SampleCode.h */,
00ED8C6A0D3E99A800651393 /* SampleCull.cpp */,
+ 0061A77A0DB7A7150007094E /* SampleFillType.cpp */,
00ED8C6B0D3E99A800651393 /* SampleDither.cpp */,
+ 00648B590DDB15B90087F2E8 /* SampleTypeface.cpp */,
003FA7090D58CA4D0063AD75 /* SampleMeasure.cpp */,
00ED8C6C0D3E99A800651393 /* SampleEncode.cpp */,
00ED8C6D0D3E99A800651393 /* SampleFilter.cpp */,
00ED8C6E0D3E99A800651393 /* SampleFontCache.cpp */,
+ 0019628F0EACBA2A00447A07 /* SamplePageFlip.cpp */,
+ 00B8EBFB0EB64ABC003C2F6F /* SampleDrawLooper.cpp */,
00ED8C6F0D3E99A800651393 /* SampleImage.cpp */,
00ED8C700D3E99A800651393 /* SampleImageDir.cpp */,
0071BCEE0D746BDF00F667CE /* SampleFilter2.cpp */,
@@ -510,6 +562,7 @@
003474EC0D5B61BA00F3F389 /* SampleVertices.cpp */,
000DC0C50D63796E00854F5A /* SampleTextAlpha.cpp */,
00ED8C710D3E99A800651393 /* SampleLayers.cpp */,
+ 00C5D2000EC00F0300C6702C /* SampleTests.cpp */,
00ED8C720D3E99A800651393 /* SamplePath.cpp */,
00ED8C730D3E99A800651393 /* SamplePathEffects.cpp */,
00ED8C740D3E99A800651393 /* SamplePoints.cpp */,
@@ -519,6 +572,9 @@
00ED8C780D3E99A800651393 /* SampleTextEffects.cpp */,
00ED8C790D3E99A800651393 /* SampleTextOnPath.cpp */,
00ED8C7A0D3E99A800651393 /* SampleTiling.cpp */,
+ 003476830DF8DEC400A270A4 /* SampleCircle.cpp */,
+ 003A10160E0C29F800136848 /* SampleOverflow.cpp */,
+ 00DB0B0D0E06CEC80061DE48 /* SampleNinePatch.cpp */,
);
name = Sources;
sourceTree = "<group>";
@@ -569,7 +625,6 @@
00ED8CB20D3E9AFA00651393 /* PBXTargetDependency */,
0013C7950D94044800B41703 /* PBXTargetDependency */,
009A741D0DA11BAE00876C03 /* PBXTargetDependency */,
- 007ECA7C0DA684CF0086775A /* PBXTargetDependency */,
0008AF100DABF9BD00477EFB /* PBXTargetDependency */,
);
name = SampleCode;
@@ -634,10 +689,6 @@
ProjectRef = 00ED8C1E0D3E999300651393 /* ports.xcodeproj */;
},
{
- ProductGroup = 007ECA720DA684A20086775A /* Products */;
- ProjectRef = 007ECA710DA684A20086775A /* pvjpeg.xcodeproj */;
- },
- {
ProductGroup = 00ED8C220D3E999300651393 /* Products */;
ProjectRef = 00ED8C210D3E999300651393 /* views.xcodeproj */;
},
@@ -668,13 +719,6 @@
remoteRef = 0013C7910D94043200B41703 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
- 007ECA760DA684A20086775A /* libpvjpeg.a */ = {
- isa = PBXReferenceProxy;
- fileType = archive.ar;
- path = libpvjpeg.a;
- remoteRef = 007ECA750DA684A20086775A /* PBXContainerItemProxy */;
- sourceTree = BUILT_PRODUCTS_DIR;
- };
009A740E0DA11B1F00876C03 /* libGL.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
@@ -784,23 +828,39 @@
00ED8C8D0D3E99A800651393 /* SampleTextEffects.cpp in Sources */,
0017F1490D6A0A6A008D9B31 /* SampleEmboss.cpp in Sources */,
0017F14A0D6A0A6A008D9B31 /* SampleLines.cpp in Sources */,
- 00ED8C7D0D3E99A800651393 /* SampleArc.cpp in Sources */,
- 00ED8C810D3E99A800651393 /* SampleEncode.cpp in Sources */,
0071BCEF0D746BDF00F667CE /* SampleFilter2.cpp in Sources */,
- 00ED8C8E0D3E99A800651393 /* SampleTextOnPath.cpp in Sources */,
00D315710D5A5B1D004B2209 /* SampleBitmapRect.cpp in Sources */,
- 00ED8C850D3E99A800651393 /* SampleImageDir.cpp in Sources */,
00ED8C7E0D3E99A800651393 /* SampleCamera.cpp in Sources */,
003474ED0D5B61BA00F3F389 /* SampleVertices.cpp in Sources */,
- 00ED8C800D3E99A800651393 /* SampleDither.cpp in Sources */,
000DC0C60D63796E00854F5A /* SampleTextAlpha.cpp in Sources */,
- 00ED8C840D3E99A800651393 /* SampleImage.cpp in Sources */,
00ED8C8F0D3E99A800651393 /* SampleTiling.cpp in Sources */,
- 000A1CB00DA522ED003DAC04 /* SamplePolyToPoly.cpp in Sources */,
00ED8C890D3E99A800651393 /* SamplePoints.cpp in Sources */,
- 0017F14B0D6A0A6A008D9B31 /* SamplePatch.cpp in Sources */,
- 00ED8C860D3E99A800651393 /* SampleLayers.cpp in Sources */,
00ED8C880D3E99A800651393 /* SamplePathEffects.cpp in Sources */,
+ 00ED8C8E0D3E99A800651393 /* SampleTextOnPath.cpp in Sources */,
+ 00648B5A0DDB15B90087F2E8 /* SampleTypeface.cpp in Sources */,
+ 00ED8C840D3E99A800651393 /* SampleImage.cpp in Sources */,
+ 0007A8F30DB4DFF30068AF40 /* SampleXfermodes.cpp in Sources */,
+ 002919440DEBA08100AF67D5 /* SkBitmapFilter.cpp in Sources */,
+ 002919510DEC39C700AF67D5 /* SkConvolutionBitmapFilter.cpp in Sources */,
+ 001142AB0DCA20650070D0A3 /* SamplePicture.cpp in Sources */,
+ 00298C2A0E7085E7005E85ED /* SampleStrokeText.cpp in Sources */,
+ 00ED8C810D3E99A800651393 /* SampleEncode.cpp in Sources */,
+ 000A1CB00DA522ED003DAC04 /* SamplePolyToPoly.cpp in Sources */,
+ 00F9D6860E7F51680031AAA2 /* SkSetPoly3To3_A.cpp in Sources */,
+ 0019628A0EACB9D300447A07 /* SamplePatch.cpp in Sources */,
+ 001962900EACBA2A00447A07 /* SamplePageFlip.cpp in Sources */,
+ 00ED8C860D3E99A800651393 /* SampleLayers.cpp in Sources */,
+ 00C5D1E10EBFFE4D00C6702C /* test.cpp in Sources */,
+ 00C5D1E50EC0007400C6702C /* test_drawcolor.cpp in Sources */,
+ 00C5D2010EC00F0300C6702C /* SampleTests.cpp in Sources */,
+ 00C5D20E0EC0106F00C6702C /* test_drawrect.cpp in Sources */,
+ 00ED8C850D3E99A800651393 /* SampleImageDir.cpp in Sources */,
+ 003A10170E0C29F800136848 /* SampleOverflow.cpp in Sources */,
+ 00ED8C800D3E99A800651393 /* SampleDither.cpp in Sources */,
+ 00ED8C7D0D3E99A800651393 /* SampleArc.cpp in Sources */,
+ 0061A77B0DB7A7150007094E /* SampleFillType.cpp in Sources */,
+ 003476840DF8DEC400A270A4 /* SampleCircle.cpp in Sources */,
+ 00B8EBFC0EB64ABC003C2F6F /* SampleDrawLooper.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -817,11 +877,6 @@
name = animator;
targetProxy = 0013C7940D94044800B41703 /* PBXContainerItemProxy */;
};
- 007ECA7C0DA684CF0086775A /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- name = pvjpeg;
- targetProxy = 007ECA7B0DA684CF0086775A /* PBXContainerItemProxy */;
- };
009A741D0DA11BAE00876C03 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = GL;
@@ -943,17 +998,24 @@
isa = XCBuildConfiguration;
buildSettings = {
GCC_CW_ASM_SYNTAX = NO;
+ GCC_DEBUGGING_SYMBOLS = full;
GCC_ENABLE_ASM_KEYWORD = NO;
+ GCC_ENABLE_CPP_EXCEPTIONS = NO;
GCC_ENABLE_CPP_RTTI = NO;
GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_ENABLE_SYMBOL_SEPARATION = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREFIX_HEADER = " ";
GCC_PREPROCESSOR_DEFINITIONS = (
SK_DEBUG,
SK_BUILD_FOR_MAC,
);
+ GCC_THREADSAFE_STATICS = NO;
GCC_USE_GCC3_PFE_SUPPORT = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
PREBINDING = NO;
+ PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk";
USER_HEADER_SEARCH_PATHS = "../../../include/corecg/** ../../../include/graphics/**";
};
@@ -967,17 +1029,27 @@
i386,
);
GCC_CW_ASM_SYNTAX = NO;
+ GCC_DEBUGGING_SYMBOLS = full;
GCC_ENABLE_ASM_KEYWORD = NO;
+ GCC_ENABLE_CPP_EXCEPTIONS = NO;
GCC_ENABLE_CPP_RTTI = NO;
GCC_ENABLE_PASCAL_STRINGS = NO;
+ GCC_ENABLE_SYMBOL_SEPARATION = NO;
+ GCC_PRECOMPILE_PREFIX_HEADER = NO;
GCC_PREPROCESSOR_DEFINITIONS = (
SK_BUILD_FOR_MAC,
SK_RELEASE,
);
+ GCC_THREADSAFE_STATICS = NO;
GCC_USE_GCC3_PFE_SUPPORT = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
+ GCC_WARN_PEDANTIC = NO;
+ GCC_WARN_SHADOW = YES;
+ GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
PREBINDING = NO;
+ PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk";
USER_HEADER_SEARCH_PATHS = "../../../include/corecg/** ../../../include/graphics/**";
};
diff --git a/ide/xcode/graphics.xcodeproj/project.pbxproj b/ide/xcode/graphics.xcodeproj/project.pbxproj
index 8f0d4fa..0eabe53 100644
--- a/ide/xcode/graphics.xcodeproj/project.pbxproj
+++ b/ide/xcode/graphics.xcodeproj/project.pbxproj
@@ -18,10 +18,11 @@
001142D70DCA3EE90070D0A3 /* SkPicturePlayback.h in Headers */ = {isa = PBXBuildFile; fileRef = 001142D30DCA3EE90070D0A3 /* SkPicturePlayback.h */; };
001142D80DCA3EE90070D0A3 /* SkPictureRecord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 001142D40DCA3EE90070D0A3 /* SkPictureRecord.cpp */; };
001142D90DCA3EE90070D0A3 /* SkPictureRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 001142D50DCA3EE90070D0A3 /* SkPictureRecord.h */; };
- 001142F70DCA3FDF0070D0A3 /* SkReader32.h in Headers */ = {isa = PBXBuildFile; fileRef = 001142F50DCA3FDF0070D0A3 /* SkReader32.h */; };
- 001142F80DCA3FDF0070D0A3 /* SkWriter32.h in Headers */ = {isa = PBXBuildFile; fileRef = 001142F60DCA3FDF0070D0A3 /* SkWriter32.h */; };
0011430B0DCA458A0070D0A3 /* SkPictureFlat.h in Headers */ = {isa = PBXBuildFile; fileRef = 0011430A0DCA458A0070D0A3 /* SkPictureFlat.h */; };
0011430D0DCA45990070D0A3 /* SkPictureFlat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0011430C0DCA45990070D0A3 /* SkPictureFlat.cpp */; };
+ 0019627D0EACB91200447A07 /* SkPageFlipper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0019627C0EACB91200447A07 /* SkPageFlipper.cpp */; };
+ 0019627F0EACB92A00447A07 /* SkFlipPixelRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0019627E0EACB92A00447A07 /* SkFlipPixelRef.cpp */; };
+ 001962810EACB94400447A07 /* SkPathHeap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 001962800EACB94400447A07 /* SkPathHeap.cpp */; };
001FFBBD0CD8D9ED000CDF07 /* SkImageRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 001FFBBC0CD8D9ED000CDF07 /* SkImageRef.cpp */; };
0027DCD00B24CA3900076079 /* SkDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0027DCCF0B24CA3900076079 /* SkDevice.cpp */; };
0027DCD20B24CA4E00076079 /* SkDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 0027DCD10B24CA4E00076079 /* SkDevice.h */; };
@@ -64,7 +65,6 @@
00523EA30C7B335D00D53402 /* SkRadialGradient_Table.h in Headers */ = {isa = PBXBuildFile; fileRef = 00523E920C7B335D00D53402 /* SkRadialGradient_Table.h */; };
00523EA40C7B335D00D53402 /* SkTransparentShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00523E930C7B335D00D53402 /* SkTransparentShader.cpp */; };
00523EA50C7B335D00D53402 /* SkUnitMappers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00523E940C7B335D00D53402 /* SkUnitMappers.cpp */; };
- 00523EA70C7B339000D53402 /* SkPicture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00523EA60C7B339000D53402 /* SkPicture.cpp */; };
00523EA90C7B33B100D53402 /* SkUnitMappers.h in Headers */ = {isa = PBXBuildFile; fileRef = 00523EA80C7B33B100D53402 /* SkUnitMappers.h */; };
00523F420C7B3C1400D53402 /* SkFlattenable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00523F410C7B3C1400D53402 /* SkFlattenable.cpp */; };
0053B0EE0D3557960016606F /* SkPaintFlagsDrawFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0053B0ED0D3557960016606F /* SkPaintFlagsDrawFilter.cpp */; };
@@ -89,7 +89,9 @@
00A159D10C469A1200DB6CED /* SkBlitRow.h in Headers */ = {isa = PBXBuildFile; fileRef = 00A159CD0C469A1200DB6CED /* SkBlitRow.h */; };
00A159D20C469A1200DB6CED /* SkDither.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00A159CE0C469A1200DB6CED /* SkDither.cpp */; };
00A2188A0B652EEC0056CB69 /* SkMask.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00A218890B652EEC0056CB69 /* SkMask.cpp */; };
+ 00B4AC4F0E9BF59400A184BF /* SkPicture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00B4AC4E0E9BF59400A184BF /* SkPicture.cpp */; };
00B5022D09DB127D00A01CD6 /* SkRegionPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 00B5022C09DB127D00A01CD6 /* SkRegionPriv.h */; };
+ 00B8EC940EB6A319003C2F6F /* SkLayerDrawLooper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00B8EC930EB6A319003C2F6F /* SkLayerDrawLooper.cpp */; };
00C88FEF0D89B7920015D427 /* SkUnPreMultiply.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00C88FEE0D89B7920015D427 /* SkUnPreMultiply.cpp */; };
FE20DF0C0C7F154F00AAC91E /* SkKernel33MaskFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE20DF0B0C7F154F00AAC91E /* SkKernel33MaskFilter.cpp */; };
FE20DF200C7F157B00AAC91E /* SkMovie.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE20DF160C7F157B00AAC91E /* SkMovie.cpp */; };
@@ -259,10 +261,11 @@
001142D30DCA3EE90070D0A3 /* SkPicturePlayback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SkPicturePlayback.h; path = ../../libs/graphics/picture/SkPicturePlayback.h; sourceTree = SOURCE_ROOT; };
001142D40DCA3EE90070D0A3 /* SkPictureRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkPictureRecord.cpp; path = ../../libs/graphics/picture/SkPictureRecord.cpp; sourceTree = SOURCE_ROOT; };
001142D50DCA3EE90070D0A3 /* SkPictureRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SkPictureRecord.h; path = ../../libs/graphics/picture/SkPictureRecord.h; sourceTree = SOURCE_ROOT; };
- 001142F50DCA3FDF0070D0A3 /* SkReader32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SkReader32.h; path = ../../libs/graphics/sgl/SkReader32.h; sourceTree = SOURCE_ROOT; };
- 001142F60DCA3FDF0070D0A3 /* SkWriter32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SkWriter32.h; path = ../../libs/graphics/sgl/SkWriter32.h; sourceTree = SOURCE_ROOT; };
0011430A0DCA458A0070D0A3 /* SkPictureFlat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SkPictureFlat.h; path = ../../libs/graphics/picture/SkPictureFlat.h; sourceTree = SOURCE_ROOT; };
0011430C0DCA45990070D0A3 /* SkPictureFlat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkPictureFlat.cpp; path = ../../libs/graphics/picture/SkPictureFlat.cpp; sourceTree = SOURCE_ROOT; };
+ 0019627C0EACB91200447A07 /* SkPageFlipper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkPageFlipper.cpp; path = ../../libs/corecg/SkPageFlipper.cpp; sourceTree = SOURCE_ROOT; };
+ 0019627E0EACB92A00447A07 /* SkFlipPixelRef.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkFlipPixelRef.cpp; path = ../../libs/graphics/images/SkFlipPixelRef.cpp; sourceTree = SOURCE_ROOT; };
+ 001962800EACB94400447A07 /* SkPathHeap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkPathHeap.cpp; path = ../../libs/graphics/picture/SkPathHeap.cpp; sourceTree = SOURCE_ROOT; };
001FFBBC0CD8D9ED000CDF07 /* SkImageRef.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SkImageRef.cpp; path = ../../libs/graphics/images/SkImageRef.cpp; sourceTree = SOURCE_ROOT; };
0027DCCF0B24CA3900076079 /* SkDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SkDevice.cpp; path = ../../libs/graphics/sgl/SkDevice.cpp; sourceTree = SOURCE_ROOT; };
0027DCD10B24CA4E00076079 /* SkDevice.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SkDevice.h; sourceTree = "<group>"; };
@@ -305,7 +308,6 @@
00523E920C7B335D00D53402 /* SkRadialGradient_Table.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = SkRadialGradient_Table.h; path = ../../libs/graphics/effects/SkRadialGradient_Table.h; sourceTree = SOURCE_ROOT; };
00523E930C7B335D00D53402 /* SkTransparentShader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SkTransparentShader.cpp; path = ../../libs/graphics/effects/SkTransparentShader.cpp; sourceTree = SOURCE_ROOT; };
00523E940C7B335D00D53402 /* SkUnitMappers.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SkUnitMappers.cpp; path = ../../libs/graphics/effects/SkUnitMappers.cpp; sourceTree = SOURCE_ROOT; };
- 00523EA60C7B339000D53402 /* SkPicture.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SkPicture.cpp; path = ../../libs/graphics/sgl/SkPicture.cpp; sourceTree = SOURCE_ROOT; };
00523EA80C7B33B100D53402 /* SkUnitMappers.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SkUnitMappers.h; sourceTree = "<group>"; };
00523F410C7B3C1400D53402 /* SkFlattenable.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SkFlattenable.cpp; path = ../../libs/graphics/sgl/SkFlattenable.cpp; sourceTree = SOURCE_ROOT; };
0053B0ED0D3557960016606F /* SkPaintFlagsDrawFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SkPaintFlagsDrawFilter.cpp; path = ../../libs/graphics/effects/SkPaintFlagsDrawFilter.cpp; sourceTree = SOURCE_ROOT; };
@@ -330,7 +332,9 @@
00A159CD0C469A1200DB6CED /* SkBlitRow.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = SkBlitRow.h; path = ../../libs/graphics/sgl/SkBlitRow.h; sourceTree = SOURCE_ROOT; };
00A159CE0C469A1200DB6CED /* SkDither.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SkDither.cpp; path = ../../libs/graphics/sgl/SkDither.cpp; sourceTree = SOURCE_ROOT; };
00A218890B652EEC0056CB69 /* SkMask.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SkMask.cpp; path = ../../libs/graphics/sgl/SkMask.cpp; sourceTree = SOURCE_ROOT; };
+ 00B4AC4E0E9BF59400A184BF /* SkPicture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkPicture.cpp; path = ../../libs/graphics/picture/SkPicture.cpp; sourceTree = SOURCE_ROOT; };
00B5022C09DB127D00A01CD6 /* SkRegionPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = SkRegionPriv.h; path = ../../libs/corecg/SkRegionPriv.h; sourceTree = SOURCE_ROOT; };
+ 00B8EC930EB6A319003C2F6F /* SkLayerDrawLooper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkLayerDrawLooper.cpp; path = ../../libs/graphics/effects/SkLayerDrawLooper.cpp; sourceTree = SOURCE_ROOT; };
00C88FEE0D89B7920015D427 /* SkUnPreMultiply.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkUnPreMultiply.cpp; path = ../../libs/graphics/sgl/SkUnPreMultiply.cpp; sourceTree = SOURCE_ROOT; };
D2AAC06F0554671400DB518D /* libgraphics.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libgraphics.a; sourceTree = BUILT_PRODUCTS_DIR; };
FE20DF0B0C7F154F00AAC91E /* SkKernel33MaskFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SkKernel33MaskFilter.cpp; path = ../../libs/graphics/effects/SkKernel33MaskFilter.cpp; sourceTree = SOURCE_ROOT; };
@@ -503,9 +507,8 @@
001142D10DCA3ED10070D0A3 /* picture */ = {
isa = PBXGroup;
children = (
- 00523EA60C7B339000D53402 /* SkPicture.cpp */,
- 001142F50DCA3FDF0070D0A3 /* SkReader32.h */,
- 001142F60DCA3FDF0070D0A3 /* SkWriter32.h */,
+ 001962800EACB94400447A07 /* SkPathHeap.cpp */,
+ 00B4AC4E0E9BF59400A184BF /* SkPicture.cpp */,
001142D20DCA3EE90070D0A3 /* SkPicturePlayback.cpp */,
001142D30DCA3EE90070D0A3 /* SkPicturePlayback.h */,
001142D40DCA3EE90070D0A3 /* SkPictureRecord.cpp */,
@@ -657,6 +660,8 @@
FE5F48C5094797E90095980F /* images */ = {
isa = PBXGroup;
children = (
+ 0019627E0EACB92A00447A07 /* SkFlipPixelRef.cpp */,
+ 0019627C0EACB91200447A07 /* SkPageFlipper.cpp */,
003FF1670DAE9C0F00601F6B /* SkImageRef_GlobalPool.cpp */,
009A39620DAE52FA00EB3A73 /* SkImageRefPool.cpp */,
008180E60D92D57300A2E56D /* SkScaledBitmapSampler.cpp */,
@@ -671,6 +676,7 @@
FE5F48C8094798660095980F /* effects */ = {
isa = PBXGroup;
children = (
+ 00B8EC930EB6A319003C2F6F /* SkLayerDrawLooper.cpp */,
009A75E90DA1DF8400876C03 /* SkNinePatch.cpp */,
0053B0ED0D3557960016606F /* SkPaintFlagsDrawFilter.cpp */,
003E6EFC0D09EF84005435C0 /* SkColorMatrix.cpp */,
@@ -939,8 +945,6 @@
009A75E80DA1DF5D00876C03 /* SkDrawProcs.h in Headers */,
001142D70DCA3EE90070D0A3 /* SkPicturePlayback.h in Headers */,
001142D90DCA3EE90070D0A3 /* SkPictureRecord.h in Headers */,
- 001142F70DCA3FDF0070D0A3 /* SkReader32.h in Headers */,
- 001142F80DCA3FDF0070D0A3 /* SkWriter32.h in Headers */,
0011430B0DCA458A0070D0A3 /* SkPictureFlat.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1026,7 +1030,6 @@
00523EA10C7B335D00D53402 /* SkGradientShader.cpp in Sources */,
00523EA40C7B335D00D53402 /* SkTransparentShader.cpp in Sources */,
00523EA50C7B335D00D53402 /* SkUnitMappers.cpp in Sources */,
- 00523EA70C7B339000D53402 /* SkPicture.cpp in Sources */,
00523F420C7B3C1400D53402 /* SkFlattenable.cpp in Sources */,
FE20DF0C0C7F154F00AAC91E /* SkKernel33MaskFilter.cpp in Sources */,
FE20DF200C7F157B00AAC91E /* SkMovie.cpp in Sources */,
@@ -1094,6 +1097,11 @@
0011430D0DCA45990070D0A3 /* SkPictureFlat.cpp in Sources */,
009B1EAE0DD224CF00EDFFF4 /* SkPixelRef.cpp in Sources */,
007336190DDC859F00A0DB2A /* SkPtrRecorder.cpp in Sources */,
+ 00B4AC4F0E9BF59400A184BF /* SkPicture.cpp in Sources */,
+ 0019627D0EACB91200447A07 /* SkPageFlipper.cpp in Sources */,
+ 0019627F0EACB92A00447A07 /* SkFlipPixelRef.cpp in Sources */,
+ 001962810EACB94400447A07 /* SkPathHeap.cpp in Sources */,
+ 00B8EC940EB6A319003C2F6F /* SkLayerDrawLooper.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/pdk/README b/pdk/README
new file mode 100644
index 0000000..b382a10
--- /dev/null
+++ b/pdk/README
@@ -0,0 +1,62 @@
+Building the pdk
+
+1) get a cupcake source tree
+
+2) from the root
+ . build/envsetup.sh
+
+3) run choosecombo
+ Build for the simulator or the device?
+ 1. Device
+ 2. Simulator
+
+ Which would you like? [1] 1
+
+
+ Build type choices are:
+ 1. release
+ 2. debug
+
+ Which would you like? [1] 1
+
+
+ Product choices are:
+ 0. emulator
+ 1. generic
+ 2. sim
+ 3. surf
+ You can also type the name of a product if you know it.
+ Which would you like? [generic] 1
+
+
+ Variant choices are:
+ 1. user
+ 2. userdebug
+ 3. eng
+ Which would you like? [eng] 3
+
+ ============================================
+ TARGET_PRODUCT=generic
+ TARGET_BUILD_VARIANT=eng
+ TARGET_SIMULATOR=false
+ TARGET_BUILD_TYPE=release
+ TARGET_ARCH=arm
+ HOST_ARCH=x86
+ HOST_OS=linux
+ HOST_BUILD_TYPE=release
+ BUILD_ID=
+ ============================================
+
+4) mkdir dist
+ mkdir logs
+ mkpdkcupcake.sh
+
+(which contains:
+
+DT=`date +%y%m%d-%H%M%S`
+#time make -j4 PRODUCT-generic-eng pdk dist DIST_DIR=dist 2>&1 | tee logs/$DT
+time make -j4 pdk dist DIST_DIR=dist 2>&1 | tee logs/$DT
+
+so you can see the results of the build in the logs directory.)
+
+5) the pdk tar file is put in the dist directory.
diff --git a/pdk/docs/_audio_hardware_interface_8h-source.html b/pdk/docs/_audio_hardware_interface_8h-source.html
new file mode 100755
index 0000000..799b827
--- /dev/null
+++ b/pdk/docs/_audio_hardware_interface_8h-source.html
@@ -0,0 +1,268 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li class="current"><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+</div>
+<h1>AudioHardwareInterface.h</h1><a href="_audio_hardware_interface_8h.html">Go to the documentation of this file.</a><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*</span>
+<a name="l00002"></a>00002 <span class="comment"> * Copyright (C) 2007 The Android Open Source Project</span>
+<a name="l00003"></a>00003 <span class="comment"> *</span>
+<a name="l00004"></a>00004 <span class="comment"> * Licensed under the Apache License, Version 2.0 (the "License");</span>
+<a name="l00005"></a>00005 <span class="comment"> * you may not use this file except in compliance with the License.</span>
+<a name="l00006"></a>00006 <span class="comment"> * You may obtain a copy of the License at</span>
+<a name="l00007"></a>00007 <span class="comment"> *</span>
+<a name="l00008"></a>00008 <span class="comment"> * http://www.apache.org/licenses/LICENSE-2.0</span>
+<a name="l00009"></a>00009 <span class="comment"> *</span>
+<a name="l00010"></a>00010 <span class="comment"> * Unless required by applicable law or agreed to in writing, software</span>
+<a name="l00011"></a>00011 <span class="comment"> * distributed under the License is distributed on an "AS IS" BASIS,</span>
+<a name="l00012"></a>00012 <span class="comment"> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span>
+<a name="l00013"></a>00013 <span class="comment"> * See the License for the specific language governing permissions and</span>
+<a name="l00014"></a>00014 <span class="comment"> * limitations under the License.</span>
+<a name="l00015"></a>00015 <span class="comment"> */</span>
+<a name="l00016"></a>00016
+<a name="l00017"></a>00017 <span class="preprocessor">#ifndef ANDROID_AUDIO_HARDWARE_INTERFACE_H</span>
+<a name="l00018"></a>00018 <span class="preprocessor"></span><span class="preprocessor">#define ANDROID_AUDIO_HARDWARE_INTERFACE_H</span>
+<a name="l00019"></a>00019 <span class="preprocessor"></span>
+<a name="l00020"></a>00020 <span class="preprocessor">#include <stdint.h></span>
+<a name="l00021"></a>00021 <span class="preprocessor">#include <sys/types.h></span>
+<a name="l00022"></a>00022
+<a name="l00023"></a>00023 <span class="preprocessor">#include <utils/Errors.h></span>
+<a name="l00024"></a>00024 <span class="preprocessor">#include <utils/Vector.h></span>
+<a name="l00025"></a>00025 <span class="preprocessor">#include <utils/String16.h></span>
+<a name="l00026"></a>00026
+<a name="l00027"></a>00027 <span class="preprocessor">#include <media/IAudioFlinger.h></span>
+<a name="l00028"></a>00028 <span class="preprocessor">#include "media/AudioSystem.h"</span>
+<a name="l00029"></a>00029
+<a name="l00030"></a>00030
+<a name="l00031"></a><a class="code" href="namespaceandroid.html">00031</a> <span class="keyword">namespace </span>android {
+<a name="l00032"></a>00032
+<a name="l00033"></a>00033 <span class="comment">// ----------------------------------------------------------------------------</span>
+<a name="l00034"></a>00034 <span class="comment"></span>
+<a name="l00035"></a>00035 <span class="comment">/**</span>
+<a name="l00036"></a>00036 <span class="comment"> * AudioStreamOut is the abstraction interface for the audio output hardware.</span>
+<a name="l00037"></a>00037 <span class="comment"> *</span>
+<a name="l00038"></a>00038 <span class="comment"> * It provides information about various properties of the audio output hardware driver.</span>
+<a name="l00039"></a>00039 <span class="comment"> */</span>
+<a name="l00040"></a><a class="code" href="classandroid_1_1_audio_stream_out.html">00040</a> <span class="keyword">class </span><a class="code" href="classandroid_1_1_audio_stream_out.html" title="AudioStreamOut is the abstraction interface for the audio output hardware.">AudioStreamOut</a> {
+<a name="l00041"></a>00041 <span class="keyword">public</span>:
+<a name="l00042"></a>00042 <span class="keyword">virtual</span> <a class="code" href="classandroid_1_1_audio_stream_out.html#09074dbae95b82d4f83c513035a0034f">~AudioStreamOut</a>() = 0;
+<a name="l00043"></a>00043 <span class="comment"></span>
+<a name="l00044"></a>00044 <span class="comment"> /** return audio sampling rate in hz - eg. 44100 */</span>
+<a name="l00045"></a>00045 <span class="keyword">virtual</span> uint32_t <a class="code" href="classandroid_1_1_audio_stream_out.html#6bb028e125d13289f26d3d74f851c921" title="return audio sampling rate in hz - eg.">sampleRate</a>() <span class="keyword">const</span> = 0;
+<a name="l00046"></a>00046 <span class="comment"></span>
+<a name="l00047"></a>00047 <span class="comment"> /** returns size of output buffer - eg. 4800 */</span>
+<a name="l00048"></a>00048 <span class="keyword">virtual</span> <span class="keywordtype">size_t</span> <a class="code" href="classandroid_1_1_audio_stream_out.html#7b3c5f2ce79b9b6f167408f63d19af0a" title="returns size of output buffer - eg.">bufferSize</a>() <span class="keyword">const</span> = 0;
+<a name="l00049"></a>00049 <span class="comment"></span>
+<a name="l00050"></a>00050 <span class="comment"> /**</span>
+<a name="l00051"></a>00051 <span class="comment"> * return number of output audio channels.</span>
+<a name="l00052"></a>00052 <span class="comment"> * Acceptable values are 1 (mono) or 2 (stereo)</span>
+<a name="l00053"></a>00053 <span class="comment"> */</span>
+<a name="l00054"></a>00054 <span class="keyword">virtual</span> <span class="keywordtype">int</span> <a class="code" href="classandroid_1_1_audio_stream_out.html#4e880a5379c168e8f68c26827e41275b" title="return number of output audio channels.">channelCount</a>() <span class="keyword">const</span> = 0;
+<a name="l00055"></a>00055 <span class="comment"></span>
+<a name="l00056"></a>00056 <span class="comment"> /**</span>
+<a name="l00057"></a>00057 <span class="comment"> * return audio format in 8bit or 16bit PCM format -</span>
+<a name="l00058"></a>00058 <span class="comment"> * eg. AudioSystem:PCM_16_BIT</span>
+<a name="l00059"></a>00059 <span class="comment"> */</span>
+<a name="l00060"></a>00060 <span class="keyword">virtual</span> <span class="keywordtype">int</span> <a class="code" href="classandroid_1_1_audio_stream_out.html#eb2b430bbff4eebd8fb8590507b1dce1" title="return audio format in 8bit or 16bit PCM format - eg.">format</a>() <span class="keyword">const</span> = 0;
+<a name="l00061"></a>00061 <span class="comment"></span>
+<a name="l00062"></a>00062 <span class="comment"> /**</span>
+<a name="l00063"></a>00063 <span class="comment"> * return the frame size (number of bytes per sample).</span>
+<a name="l00064"></a>00064 <span class="comment"> */</span>
+<a name="l00065"></a><a class="code" href="classandroid_1_1_audio_stream_out.html#66b7c4bb510db4060adfd03a376897d8">00065</a> uint32_t <a class="code" href="classandroid_1_1_audio_stream_out.html#66b7c4bb510db4060adfd03a376897d8" title="return the frame size (number of bytes per sample).">frameSize</a>()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> <a class="code" href="classandroid_1_1_audio_stream_out.html#4e880a5379c168e8f68c26827e41275b" title="return number of output audio channels.">channelCount</a>()*((<a class="code" href="classandroid_1_1_audio_stream_out.html#eb2b430bbff4eebd8fb8590507b1dce1" title="return audio format in 8bit or 16bit PCM format - eg.">format</a>()==AudioSystem::PCM_16_BIT)?<span class="keyword">sizeof</span>(int16_t):<span class="keyword">sizeof</span>(int8_t)); }
+<a name="l00066"></a>00066 <span class="comment"></span>
+<a name="l00067"></a>00067 <span class="comment"> /**</span>
+<a name="l00068"></a>00068 <span class="comment"> * return the audio hardware driver latency in milli seconds.</span>
+<a name="l00069"></a>00069 <span class="comment"> */</span>
+<a name="l00070"></a>00070 <span class="keyword">virtual</span> uint32_t <a class="code" href="classandroid_1_1_audio_stream_out.html#c698a3d95cf0829dcfe283cd5ea437cb" title="return the audio hardware driver latency in milli seconds.">latency</a>() <span class="keyword">const</span> = 0;
+<a name="l00071"></a>00071 <span class="comment"></span>
+<a name="l00072"></a>00072 <span class="comment"> /**</span>
+<a name="l00073"></a>00073 <span class="comment"> * Use this method in situations where audio mixing is done in the</span>
+<a name="l00074"></a>00074 <span class="comment"> * hardware. This method serves as a direct interface with hardware,</span>
+<a name="l00075"></a>00075 <span class="comment"> * allowing you to directly set the volume as apposed to via the framework.</span>
+<a name="l00076"></a>00076 <span class="comment"> * This method might produce multiple PCM outputs or hardware accelerated</span>
+<a name="l00077"></a>00077 <span class="comment"> * codecs, such as MP3 or AAC.</span>
+<a name="l00078"></a>00078 <span class="comment"> */</span>
+<a name="l00079"></a>00079 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_audio_stream_out.html#e6d301925d193c25561b42239c7f44b6" title="Use this method in situations where audio mixing is done in the hardware.">setVolume</a>(<span class="keywordtype">float</span> volume) = 0;
+<a name="l00080"></a>00080 <span class="comment"></span>
+<a name="l00081"></a>00081 <span class="comment"> /** write audio buffer to driver. Returns number of bytes written */</span>
+<a name="l00082"></a>00082 <span class="keyword">virtual</span> ssize_t <a class="code" href="classandroid_1_1_audio_stream_out.html#cba177e4a4a35a87ab9f8aa2a9c0e78e" title="write audio buffer to driver.">write</a>(<span class="keyword">const</span> <span class="keywordtype">void</span>* buffer, <span class="keywordtype">size_t</span> bytes) = 0;
+<a name="l00083"></a>00083 <span class="comment"></span>
+<a name="l00084"></a>00084 <span class="comment"> /** dump the state of the audio output device */</span>
+<a name="l00085"></a>00085 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_audio_stream_out.html#97e3cc4610ba40d6c37b3d376a032b98" title="dump the state of the audio output device">dump</a>(<span class="keywordtype">int</span> fd, <span class="keyword">const</span> Vector<String16>& args) = 0;
+<a name="l00086"></a>00086 };
+<a name="l00087"></a>00087 <span class="comment"></span>
+<a name="l00088"></a>00088 <span class="comment">/**</span>
+<a name="l00089"></a>00089 <span class="comment"> * AudioStreamIn is the abstraction interface for the audio input hardware.</span>
+<a name="l00090"></a>00090 <span class="comment"> *</span>
+<a name="l00091"></a>00091 <span class="comment"> * It defines the various properties of the audio hardware input driver.</span>
+<a name="l00092"></a>00092 <span class="comment"> */</span>
+<a name="l00093"></a><a class="code" href="classandroid_1_1_audio_stream_in.html">00093</a> <span class="keyword">class </span><a class="code" href="classandroid_1_1_audio_stream_in.html" title="AudioStreamIn is the abstraction interface for the audio input hardware.">AudioStreamIn</a> {
+<a name="l00094"></a>00094 <span class="keyword">public</span>:
+<a name="l00095"></a>00095 <span class="keyword">virtual</span> <a class="code" href="classandroid_1_1_audio_stream_in.html#72067577568bbdd0163c1369fe80f101">~AudioStreamIn</a>() = 0;
+<a name="l00096"></a>00096 <span class="comment"></span>
+<a name="l00097"></a>00097 <span class="comment"> /** return the input buffer size allowed by audio driver */</span>
+<a name="l00098"></a>00098 <span class="keyword">virtual</span> <span class="keywordtype">size_t</span> <a class="code" href="classandroid_1_1_audio_stream_in.html#a458f9cde3edde82f256af7eaa7b2ddf" title="return the input buffer size allowed by audio driver">bufferSize</a>() <span class="keyword">const</span> = 0;
+<a name="l00099"></a>00099 <span class="comment"></span>
+<a name="l00100"></a>00100 <span class="comment"> /** return the number of audio input channels */</span>
+<a name="l00101"></a>00101 <span class="keyword">virtual</span> <span class="keywordtype">int</span> <a class="code" href="classandroid_1_1_audio_stream_in.html#04f84006dd5f2e0a5e512897a039f851" title="return the number of audio input channels">channelCount</a>() <span class="keyword">const</span> = 0;
+<a name="l00102"></a>00102 <span class="comment"></span>
+<a name="l00103"></a>00103 <span class="comment"> /**</span>
+<a name="l00104"></a>00104 <span class="comment"> * return audio format in 8bit or 16bit PCM format -</span>
+<a name="l00105"></a>00105 <span class="comment"> * eg. AudioSystem:PCM_16_BIT</span>
+<a name="l00106"></a>00106 <span class="comment"> */</span>
+<a name="l00107"></a>00107 <span class="keyword">virtual</span> <span class="keywordtype">int</span> <a class="code" href="classandroid_1_1_audio_stream_in.html#4ade98c5243b9ed5f3a71a8f36e74b36" title="return audio format in 8bit or 16bit PCM format - eg.">format</a>() <span class="keyword">const</span> = 0;
+<a name="l00108"></a>00108 <span class="comment"></span>
+<a name="l00109"></a>00109 <span class="comment"> /**</span>
+<a name="l00110"></a>00110 <span class="comment"> * return the frame size (number of bytes per sample).</span>
+<a name="l00111"></a>00111 <span class="comment"> */</span>
+<a name="l00112"></a><a class="code" href="classandroid_1_1_audio_stream_in.html#43d2c6b97806c005f0717a7bb6f7595c">00112</a> uint32_t <a class="code" href="classandroid_1_1_audio_stream_in.html#43d2c6b97806c005f0717a7bb6f7595c" title="return the frame size (number of bytes per sample).">frameSize</a>()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> <a class="code" href="classandroid_1_1_audio_stream_in.html#04f84006dd5f2e0a5e512897a039f851" title="return the number of audio input channels">channelCount</a>()*((<a class="code" href="classandroid_1_1_audio_stream_in.html#4ade98c5243b9ed5f3a71a8f36e74b36" title="return audio format in 8bit or 16bit PCM format - eg.">format</a>()==AudioSystem::PCM_16_BIT)?<span class="keyword">sizeof</span>(int16_t):<span class="keyword">sizeof</span>(int8_t)); }
+<a name="l00113"></a>00113 <span class="comment"></span>
+<a name="l00114"></a>00114 <span class="comment"> /** set the input gain for the audio driver. This method is for</span>
+<a name="l00115"></a>00115 <span class="comment"> * for future use */</span>
+<a name="l00116"></a>00116 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_audio_stream_in.html#339822afb3f2f2ac1b4c775d31d12440" title="set the input gain for the audio driver.">setGain</a>(<span class="keywordtype">float</span> gain) = 0;
+<a name="l00117"></a>00117 <span class="comment"></span>
+<a name="l00118"></a>00118 <span class="comment"> /** read audio buffer in from audio driver */</span>
+<a name="l00119"></a>00119 <span class="keyword">virtual</span> ssize_t <a class="code" href="classandroid_1_1_audio_stream_in.html#7c313cbfbb47dafd90f3225bcd26e592" title="read audio buffer in from audio driver">read</a>(<span class="keywordtype">void</span>* buffer, ssize_t bytes) = 0;
+<a name="l00120"></a>00120 <span class="comment"></span>
+<a name="l00121"></a>00121 <span class="comment"> /** dump the state of the audio input device */</span>
+<a name="l00122"></a>00122 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_audio_stream_in.html#18c3760208bfb99498715a0d4977f675" title="dump the state of the audio input device">dump</a>(<span class="keywordtype">int</span> fd, <span class="keyword">const</span> Vector<String16>& args) = 0;
+<a name="l00123"></a>00123 <span class="comment"></span>
+<a name="l00124"></a>00124 <span class="comment"> /**</span>
+<a name="l00125"></a>00125 <span class="comment"> * Put the audio hardware input into standby mode. Returns</span>
+<a name="l00126"></a>00126 <span class="comment"> * status based on include/utils/Errors.h</span>
+<a name="l00127"></a>00127 <span class="comment"> */</span>
+<a name="l00128"></a>00128 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_audio_stream_in.html#93fab46e8afdbaedd4d20cc6ee2b7c41" title="Put the audio hardware input into standby mode.">standby</a>() = 0;
+<a name="l00129"></a>00129
+<a name="l00130"></a>00130 };
+<a name="l00131"></a>00131 <span class="comment"></span>
+<a name="l00132"></a>00132 <span class="comment">/**</span>
+<a name="l00133"></a>00133 <span class="comment"> * AudioHardwareInterface.h defines the interface to the audio hardware abstraction layer.</span>
+<a name="l00134"></a>00134 <span class="comment"> *</span>
+<a name="l00135"></a>00135 <span class="comment"> * The interface supports setting and getting parameters, selecting audio routing</span>
+<a name="l00136"></a>00136 <span class="comment"> * paths, and defining input and output streams.</span>
+<a name="l00137"></a>00137 <span class="comment"> *</span>
+<a name="l00138"></a>00138 <span class="comment"> * AudioFlinger initializes the audio hardware and immediately opens an output stream.</span>
+<a name="l00139"></a>00139 <span class="comment"> * You can set Audio routing to output to handset, speaker, Bluetooth, or a headset.</span>
+<a name="l00140"></a>00140 <span class="comment"> *</span>
+<a name="l00141"></a>00141 <span class="comment"> * The audio input stream is initialized when AudioFlinger is called to carry out</span>
+<a name="l00142"></a>00142 <span class="comment"> * a record operation.</span>
+<a name="l00143"></a>00143 <span class="comment"> */</span>
+<a name="l00144"></a><a class="code" href="classandroid_1_1_audio_hardware_interface.html">00144</a> <span class="keyword">class </span><a class="code" href="classandroid_1_1_audio_hardware_interface.html" title="AudioHardwareInterface.h defines the interface to the audio hardware abstraction...">AudioHardwareInterface</a>
+<a name="l00145"></a>00145 {
+<a name="l00146"></a>00146 <span class="keyword">public</span>:<span class="comment"></span>
+<a name="l00147"></a>00147 <span class="comment"> /**</span>
+<a name="l00148"></a>00148 <span class="comment"> * check to see if the audio hardware interface has been initialized.</span>
+<a name="l00149"></a>00149 <span class="comment"> * return status based on values defined in include/utils/Errors.h</span>
+<a name="l00150"></a>00150 <span class="comment"> */</span>
+<a name="l00151"></a>00151 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_audio_hardware_interface.html#b7e19e09fa6cbc07c127122fa9866c50" title="check to see if the audio hardware interface has been initialized.">initCheck</a>() = 0;
+<a name="l00152"></a>00152 <span class="comment"></span>
+<a name="l00153"></a>00153 <span class="comment"> /**</span>
+<a name="l00154"></a>00154 <span class="comment"> * put the audio hardware into standby mode to conserve power. Returns</span>
+<a name="l00155"></a>00155 <span class="comment"> * status based on include/utils/Errors.h</span>
+<a name="l00156"></a>00156 <span class="comment"> */</span>
+<a name="l00157"></a>00157 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_audio_hardware_interface.html#61121d365bb4d182bdec2c1b12fb1178" title="put the audio hardware into standby mode to conserve power.">standby</a>() = 0;
+<a name="l00158"></a>00158 <span class="comment"></span>
+<a name="l00159"></a>00159 <span class="comment"> /** set the audio volume of a voice call. Range is between 0.0 and 1.0 */</span>
+<a name="l00160"></a>00160 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_audio_hardware_interface.html#7b7418072df1eeaacc89cd0c725755f6" title="set the audio volume of a voice call.">setVoiceVolume</a>(<span class="keywordtype">float</span> volume) = 0;
+<a name="l00161"></a>00161 <span class="comment"></span>
+<a name="l00162"></a>00162 <span class="comment"> /**</span>
+<a name="l00163"></a>00163 <span class="comment"> * set the audio volume for all audio activities other than voice call.</span>
+<a name="l00164"></a>00164 <span class="comment"> * Range between 0.0 and 1.0. If any value other than NO_ERROR is returned,</span>
+<a name="l00165"></a>00165 <span class="comment"> * the software mixer will emulate this capability.</span>
+<a name="l00166"></a>00166 <span class="comment"> */</span>
+<a name="l00167"></a>00167 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_audio_hardware_interface.html#925092e556eb89f304bcebb09f90c9a3" title="set the audio volume for all audio activities other than voice call.">setMasterVolume</a>(<span class="keywordtype">float</span> volume) = 0;
+<a name="l00168"></a>00168 <span class="comment"></span>
+<a name="l00169"></a>00169 <span class="comment"> /**</span>
+<a name="l00170"></a>00170 <span class="comment"> * Audio routing methods. Routes defined in include/hardware/AudioSystem.h.</span>
+<a name="l00171"></a>00171 <span class="comment"> * Audio routes can be (ROUTE_EARPIECE | ROUTE_SPEAKER | ROUTE_BLUETOOTH</span>
+<a name="l00172"></a>00172 <span class="comment"> * | ROUTE_HEADSET)</span>
+<a name="l00173"></a>00173 <span class="comment"> *</span>
+<a name="l00174"></a>00174 <span class="comment"> * setRouting sets the routes for a mode. This is called at startup. It is</span>
+<a name="l00175"></a>00175 <span class="comment"> * also called when a new device is connected, such as a wired headset is</span>
+<a name="l00176"></a>00176 <span class="comment"> * plugged in or a Bluetooth headset is paired.</span>
+<a name="l00177"></a>00177 <span class="comment"> */</span>
+<a name="l00178"></a>00178 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_audio_hardware_interface.html#39b2690e19219425b8cff093ef83bfb1" title="Audio routing methods.">setRouting</a>(<span class="keywordtype">int</span> mode, uint32_t routes) = 0;
+<a name="l00179"></a>00179
+<a name="l00180"></a>00180 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_audio_hardware_interface.html#1886de8fff2342ae628dbbbc0c45ba83">getRouting</a>(<span class="keywordtype">int</span> mode, uint32_t* routes) = 0;
+<a name="l00181"></a>00181 <span class="comment"></span>
+<a name="l00182"></a>00182 <span class="comment"> /**</span>
+<a name="l00183"></a>00183 <span class="comment"> * setMode is called when the audio mode changes. NORMAL mode is for</span>
+<a name="l00184"></a>00184 <span class="comment"> * standard audio playback, RINGTONE when a ringtone is playing, and IN_CALL</span>
+<a name="l00185"></a>00185 <span class="comment"> * when a call is in progress.</span>
+<a name="l00186"></a>00186 <span class="comment"> */</span>
+<a name="l00187"></a>00187 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_audio_hardware_interface.html#aaf2a429c240f00b21836794849b430f" title="setMode is called when the audio mode changes.">setMode</a>(<span class="keywordtype">int</span> mode) = 0;
+<a name="l00188"></a>00188 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_audio_hardware_interface.html#8466c76328a51b8a83da103032abba55">getMode</a>(<span class="keywordtype">int</span>* mode) = 0;
+<a name="l00189"></a>00189
+<a name="l00190"></a>00190 <span class="comment">// mic mute</span>
+<a name="l00191"></a>00191 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_audio_hardware_interface.html#be35b7cb738531939a3ac9abc5514621">setMicMute</a>(<span class="keywordtype">bool</span> state) = 0;
+<a name="l00192"></a>00192 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_audio_hardware_interface.html#15d3c33d7e3f965dc2588c537f05a133">getMicMute</a>(<span class="keywordtype">bool</span>* state) = 0;
+<a name="l00193"></a>00193
+<a name="l00194"></a>00194 <span class="comment">// Temporary interface, do not use</span>
+<a name="l00195"></a>00195 <span class="comment">// TODO: Replace with a more generic key:value get/set mechanism</span>
+<a name="l00196"></a>00196 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_audio_hardware_interface.html#a1b477901df48b3a27103a77e6bb39c8">setParameter</a>(<span class="keyword">const</span> <span class="keywordtype">char</span>* key, <span class="keyword">const</span> <span class="keywordtype">char</span>* value) = 0;
+<a name="l00197"></a>00197
+<a name="l00198"></a>00198 <span class="comment">// Returns audio input buffer size according to parameters passed or 0 if one of the</span>
+<a name="l00199"></a>00199 <span class="comment">// parameters is not supported</span>
+<a name="l00200"></a>00200 <span class="keyword">virtual</span> <span class="keywordtype">size_t</span> <a class="code" href="classandroid_1_1_audio_hardware_interface.html#19f68d873b2a6e4c00c017c580170395">getInputBufferSize</a>(uint32_t sampleRate, <span class="keywordtype">int</span> format, <span class="keywordtype">int</span> channelCount) = 0;
+<a name="l00201"></a>00201 <span class="comment"></span>
+<a name="l00202"></a>00202 <span class="comment"> /** This method creates and opens the audio hardware output stream */</span>
+<a name="l00203"></a>00203 <span class="keyword">virtual</span> <a class="code" href="classandroid_1_1_audio_stream_out.html" title="AudioStreamOut is the abstraction interface for the audio output hardware.">AudioStreamOut</a>* <a class="code" href="classandroid_1_1_audio_hardware_interface.html#eda0986e145c8dd68d21cb79051f94f9" title="This method creates and opens the audio hardware output stream.">openOutputStream</a>(
+<a name="l00204"></a>00204 <span class="keywordtype">int</span> format=0,
+<a name="l00205"></a>00205 <span class="keywordtype">int</span> channelCount=0,
+<a name="l00206"></a>00206 uint32_t sampleRate=0,
+<a name="l00207"></a>00207 status_t *status=0) = 0;
+<a name="l00208"></a>00208 <span class="comment"></span>
+<a name="l00209"></a>00209 <span class="comment"> /** This method creates and opens the audio hardware input stream */</span>
+<a name="l00210"></a>00210 <span class="keyword">virtual</span> <a class="code" href="classandroid_1_1_audio_stream_in.html" title="AudioStreamIn is the abstraction interface for the audio input hardware.">AudioStreamIn</a>* <a class="code" href="classandroid_1_1_audio_hardware_interface.html#efb777d192fcbcd65458fa4f2d976476" title="This method creates and opens the audio hardware input stream.">openInputStream</a>(
+<a name="l00211"></a>00211 <span class="keywordtype">int</span> format,
+<a name="l00212"></a>00212 <span class="keywordtype">int</span> channelCount,
+<a name="l00213"></a>00213 uint32_t sampleRate,
+<a name="l00214"></a>00214 status_t *status) = 0;
+<a name="l00215"></a>00215 <span class="comment"></span>
+<a name="l00216"></a>00216 <span class="comment"> /**This method dumps the state of the audio hardware */</span>
+<a name="l00217"></a>00217 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_audio_hardware_interface.html#05f035af60e67a22251175b44a089f69" title="This method dumps the state of the audio hardware.">dumpState</a>(<span class="keywordtype">int</span> fd, <span class="keyword">const</span> Vector<String16>& args) = 0;
+<a name="l00218"></a>00218
+<a name="l00219"></a>00219 <span class="keyword">static</span> <a class="code" href="classandroid_1_1_audio_hardware_interface.html" title="AudioHardwareInterface.h defines the interface to the audio hardware abstraction...">AudioHardwareInterface</a>* <a class="code" href="classandroid_1_1_audio_hardware_interface.html#aa5ae45e9ad969fefc494e103cf5068d">create</a>();
+<a name="l00220"></a>00220
+<a name="l00221"></a>00221 <span class="keyword">protected</span>:<span class="comment"></span>
+<a name="l00222"></a>00222 <span class="comment"> /**</span>
+<a name="l00223"></a>00223 <span class="comment"> * doRouting actually initiates the routing. A call to setRouting</span>
+<a name="l00224"></a>00224 <span class="comment"> * or setMode may result in a routing change. The generic logic calls</span>
+<a name="l00225"></a>00225 <span class="comment"> * doRouting when required. If the device has any special requirements these</span>
+<a name="l00226"></a>00226 <span class="comment"> * methods can be overriden.</span>
+<a name="l00227"></a>00227 <span class="comment"> */</span>
+<a name="l00228"></a>00228 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_audio_hardware_interface.html#d82c3e4827f275abf28eb872e8751e1f" title="doRouting actually initiates the routing.">doRouting</a>() = 0;
+<a name="l00229"></a>00229
+<a name="l00230"></a>00230 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_audio_hardware_interface.html#371f198a416cb726804e0f47e8763217">dump</a>(<span class="keywordtype">int</span> fd, <span class="keyword">const</span> Vector<String16>& args) = 0;
+<a name="l00231"></a>00231 };
+<a name="l00232"></a>00232
+<a name="l00233"></a>00233 <span class="comment">// ----------------------------------------------------------------------------</span>
+<a name="l00234"></a>00234
+<a name="l00235"></a>00235 <span class="keyword">extern</span> <span class="stringliteral">"C"</span> <a class="code" href="classandroid_1_1_audio_hardware_interface.html" title="AudioHardwareInterface.h defines the interface to the audio hardware abstraction...">AudioHardwareInterface</a>* <a class="code" href="namespaceandroid.html#dcc80314ddffcb0981a9e9c5468662f8">createAudioHardware</a>(<span class="keywordtype">void</span>);
+<a name="l00236"></a>00236
+<a name="l00237"></a>00237 }; <span class="comment">// namespace android</span>
+<a name="l00238"></a>00238
+<a name="l00239"></a>00239 <span class="preprocessor">#endif // ANDROID_AUDIO_HARDWARE_INTERFACE_H</span>
+</pre></div></div>
+</body>
+</html>
diff --git a/pdk/docs/_audio_hardware_interface_8h.html b/pdk/docs/_audio_hardware_interface_8h.html
new file mode 100755
index 0000000..f45379f
--- /dev/null
+++ b/pdk/docs/_audio_hardware_interface_8h.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li class="current"><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+<h1>AudioHardwareInterface.h File Reference</h1>
+<p>
+<a href="_audio_hardware_interface_8h-source.html">Go to the source code of this file.</a><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Namespaces</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">namespace </td><td class="memItemRight" valign="bottom"><a class="el" href="namespaceandroid.html">android</a></td></tr>
+
+<tr><td colspan="2"><br><h2>Data Structures</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">class </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_out.html">android::AudioStreamOut</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight"><a class="el" href="classandroid_1_1_audio_stream_out.html" title="AudioStreamOut is the abstraction interface for the audio output hardware.">AudioStreamOut</a> is the abstraction interface for the audio output hardware. <a href="classandroid_1_1_audio_stream_out.html#_details">More...</a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">class </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_in.html">android::AudioStreamIn</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight"><a class="el" href="classandroid_1_1_audio_stream_in.html" title="AudioStreamIn is the abstraction interface for the audio input hardware.">AudioStreamIn</a> is the abstraction interface for the audio input hardware. <a href="classandroid_1_1_audio_stream_in.html#_details">More...</a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">class </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_hardware_interface.html">android::AudioHardwareInterface</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight"><a class="el" href="_audio_hardware_interface_8h.html">AudioHardwareInterface.h</a> defines the interface to the audio hardware abstraction layer. <a href="classandroid_1_1_audio_hardware_interface.html#_details">More...</a><br></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">AudioHardwareInterface * </td><td class="memItemRight" valign="bottom"><a class="el" href="namespaceandroid.html#dcc80314ddffcb0981a9e9c5468662f8">android::createAudioHardware</a> (void)</td></tr>
+
+</table>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/_camera_hardware_interface_8h-source.html b/pdk/docs/_camera_hardware_interface_8h-source.html
new file mode 100755
index 0000000..41f0a1d
--- /dev/null
+++ b/pdk/docs/_camera_hardware_interface_8h-source.html
@@ -0,0 +1,179 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li class="current"><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+</div>
+<h1>CameraHardwareInterface.h</h1><a href="_camera_hardware_interface_8h.html">Go to the documentation of this file.</a><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*</span>
+<a name="l00002"></a>00002 <span class="comment"> * Copyright (C) 2008 The Android Open Source Project</span>
+<a name="l00003"></a>00003 <span class="comment"> *</span>
+<a name="l00004"></a>00004 <span class="comment"> * Licensed under the Apache License, Version 2.0 (the "License");</span>
+<a name="l00005"></a>00005 <span class="comment"> * you may not use this file except in compliance with the License.</span>
+<a name="l00006"></a>00006 <span class="comment"> * You may obtain a copy of the License at</span>
+<a name="l00007"></a>00007 <span class="comment"> *</span>
+<a name="l00008"></a>00008 <span class="comment"> * http://www.apache.org/licenses/LICENSE-2.0</span>
+<a name="l00009"></a>00009 <span class="comment"> *</span>
+<a name="l00010"></a>00010 <span class="comment"> * Unless required by applicable law or agreed to in writing, software</span>
+<a name="l00011"></a>00011 <span class="comment"> * distributed under the License is distributed on an "AS IS" BASIS,</span>
+<a name="l00012"></a>00012 <span class="comment"> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span>
+<a name="l00013"></a>00013 <span class="comment"> * See the License for the specific language governing permissions and</span>
+<a name="l00014"></a>00014 <span class="comment"> * limitations under the License.</span>
+<a name="l00015"></a>00015 <span class="comment"> */</span>
+<a name="l00016"></a>00016
+<a name="l00017"></a>00017 <span class="preprocessor">#ifndef ANDROID_HARDWARE_CAMERA_HARDWARE_INTERFACE_H</span>
+<a name="l00018"></a>00018 <span class="preprocessor"></span><span class="preprocessor">#define ANDROID_HARDWARE_CAMERA_HARDWARE_INTERFACE_H</span>
+<a name="l00019"></a>00019 <span class="preprocessor"></span>
+<a name="l00020"></a>00020 <span class="preprocessor">#include <utils/IMemory.h></span>
+<a name="l00021"></a>00021 <span class="preprocessor">#include <utils/RefBase.h></span>
+<a name="l00022"></a>00022 <span class="preprocessor">#include <ui/CameraParameters.h></span>
+<a name="l00023"></a>00023
+<a name="l00024"></a>00024 <span class="keyword">namespace </span>android {
+<a name="l00025"></a>00025 <span class="comment"></span>
+<a name="l00026"></a>00026 <span class="comment">/** Callback for startPreview() */</span>
+<a name="l00027"></a><a class="code" href="namespaceandroid.html#d32b08663d42356404e2eb971e271636">00027</a> <span class="keyword">typedef</span> void (*<a class="code" href="namespaceandroid.html#d32b08663d42356404e2eb971e271636" title="Callback for startPreview().">preview_callback</a>)(<span class="keyword">const</span> sp<IMemory>& mem, <span class="keywordtype">void</span>* user);
+<a name="l00028"></a>00028 <span class="comment"></span>
+<a name="l00029"></a>00029 <span class="comment">/** Callback for takePicture() */</span>
+<a name="l00030"></a><a class="code" href="namespaceandroid.html#04c83209c2627e2d303320712ca9ee65">00030</a> <span class="keyword">typedef</span> void (*<a class="code" href="namespaceandroid.html#04c83209c2627e2d303320712ca9ee65" title="Callback for takePicture().">shutter_callback</a>)(<span class="keywordtype">void</span>* user);
+<a name="l00031"></a>00031 <span class="comment"></span>
+<a name="l00032"></a>00032 <span class="comment">/** Callback for takePicture() */</span>
+<a name="l00033"></a><a class="code" href="namespaceandroid.html#a97926709e452d66360cb9b24736969e">00033</a> <span class="keyword">typedef</span> void (*<a class="code" href="namespaceandroid.html#a97926709e452d66360cb9b24736969e" title="Callback for takePicture().">raw_callback</a>)(<span class="keyword">const</span> sp<IMemory>& mem, <span class="keywordtype">void</span>* user);
+<a name="l00034"></a>00034 <span class="comment"></span>
+<a name="l00035"></a>00035 <span class="comment">/** Callback for takePicture() */</span>
+<a name="l00036"></a><a class="code" href="namespaceandroid.html#c21980d4be1e0cc458399ecf5374d473">00036</a> <span class="keyword">typedef</span> void (*<a class="code" href="namespaceandroid.html#c21980d4be1e0cc458399ecf5374d473" title="Callback for takePicture().">jpeg_callback</a>)(<span class="keyword">const</span> sp<IMemory>& mem, <span class="keywordtype">void</span>* user);
+<a name="l00037"></a>00037 <span class="comment"></span>
+<a name="l00038"></a>00038 <span class="comment">/** Callback for autoFocus() */</span>
+<a name="l00039"></a><a class="code" href="namespaceandroid.html#4dca8d8b824ca9a684358133da0ec8f2">00039</a> <span class="keyword">typedef</span> void (*<a class="code" href="namespaceandroid.html#4dca8d8b824ca9a684358133da0ec8f2" title="Callback for autoFocus().">autofocus_callback</a>)(<span class="keywordtype">bool</span> focused, <span class="keywordtype">void</span>* user);
+<a name="l00040"></a>00040 <span class="comment"></span>
+<a name="l00041"></a>00041 <span class="comment">/**</span>
+<a name="l00042"></a>00042 <span class="comment"> * CameraHardwareInterface.h defines the interface to the</span>
+<a name="l00043"></a>00043 <span class="comment"> * camera hardware abstraction layer, used for setting and getting</span>
+<a name="l00044"></a>00044 <span class="comment"> * parameters, live previewing, and taking pictures.</span>
+<a name="l00045"></a>00045 <span class="comment"> *</span>
+<a name="l00046"></a>00046 <span class="comment"> * It is a referenced counted interface with RefBase as its base class.</span>
+<a name="l00047"></a>00047 <span class="comment"> * CameraService calls openCameraHardware() to retrieve a strong pointer to the</span>
+<a name="l00048"></a>00048 <span class="comment"> * instance of this interface and may be called multiple times. The</span>
+<a name="l00049"></a>00049 <span class="comment"> * following steps describe a typical sequence:</span>
+<a name="l00050"></a>00050 <span class="comment"> *</span>
+<a name="l00051"></a>00051 <span class="comment"> * -# After CameraService calls openCameraHardware(), getParameters() and</span>
+<a name="l00052"></a>00052 <span class="comment"> * setParameters() are used to initialize the camera instance.</span>
+<a name="l00053"></a>00053 <span class="comment"> * CameraService calls getPreviewHeap() to establish access to the</span>
+<a name="l00054"></a>00054 <span class="comment"> * preview heap so it can be registered with SurfaceFlinger for</span>
+<a name="l00055"></a>00055 <span class="comment"> * efficient display updating while in preview mode.</span>
+<a name="l00056"></a>00056 <span class="comment"> * -# startPreview() is called, which is passed a preview_callback()</span>
+<a name="l00057"></a>00057 <span class="comment"> * function and a user parameter. The camera instance then periodically</span>
+<a name="l00058"></a>00058 <span class="comment"> * calls preview_callback() each time a new preview frame is available.</span>
+<a name="l00059"></a>00059 <span class="comment"> * The callback routine has two parameters: the first is a pointer to</span>
+<a name="l00060"></a>00060 <span class="comment"> * the IMemory containing the frame and the second a user parameter. If</span>
+<a name="l00061"></a>00061 <span class="comment"> * the preview_callback code needs to use this memory after returning,</span>
+<a name="l00062"></a>00062 <span class="comment"> * it must copy the data.</span>
+<a name="l00063"></a>00063 <span class="comment"> *</span>
+<a name="l00064"></a>00064 <span class="comment"> * Prior to taking a picture, CameraService calls autofocus() with</span>
+<a name="l00065"></a>00065 <span class="comment"> * autofocus_callback() and a user parameter. When auto focusing has</span>
+<a name="l00066"></a>00066 <span class="comment"> * completed, the camera instance calls autofocus_callback(), which informs</span>
+<a name="l00067"></a>00067 <span class="comment"> * the application whether focusing was successful. The camera instance</span>
+<a name="l00068"></a>00068 <span class="comment"> * only calls autofocus_callback() once and it is up to the application to</span>
+<a name="l00069"></a>00069 <span class="comment"> * call autoFocus() again if refocusing is desired.</span>
+<a name="l00070"></a>00070 <span class="comment"> *</span>
+<a name="l00071"></a>00071 <span class="comment"> * CameraService calls takePicture() to request the camera instance take a</span>
+<a name="l00072"></a>00072 <span class="comment"> * picture. This method has two callbacks: raw_callback() and jpeg_callback().</span>
+<a name="l00073"></a>00073 <span class="comment"> * When the raw image is available, raw_callback() is called with a pointer</span>
+<a name="l00074"></a>00074 <span class="comment"> * to the IMemory containing the raw image. When the jpeg image is available,</span>
+<a name="l00075"></a>00075 <span class="comment"> * jpeg_callback() is called with a pointer to the IMemory containing the</span>
+<a name="l00076"></a>00076 <span class="comment"> * jpeg image. As with preview_callback(), the memory must be copied if it's</span>
+<a name="l00077"></a>00077 <span class="comment"> * needed after returning.</span>
+<a name="l00078"></a>00078 <span class="comment"> */</span>
+<a name="l00079"></a><a class="code" href="classandroid_1_1_camera_hardware_interface.html">00079</a> <span class="keyword">class </span><a class="code" href="classandroid_1_1_camera_hardware_interface.html" title="CameraHardwareInterface.h defines the interface to the camera hardware abstraction...">CameraHardwareInterface</a> : <span class="keyword">public</span> <span class="keyword">virtual</span> RefBase {
+<a name="l00080"></a>00080 <span class="keyword">public</span>:
+<a name="l00081"></a><a class="code" href="classandroid_1_1_camera_hardware_interface.html#99f4ab74b58cd4b23e0fb00a46a60cb1">00081</a> <span class="keyword">virtual</span> <a class="code" href="classandroid_1_1_camera_hardware_interface.html#99f4ab74b58cd4b23e0fb00a46a60cb1">~CameraHardwareInterface</a>() { }
+<a name="l00082"></a>00082 <span class="comment"></span>
+<a name="l00083"></a>00083 <span class="comment"> /** Return the IMemoryHeap for the preview image heap */</span>
+<a name="l00084"></a>00084 <span class="keyword">virtual</span> sp<IMemoryHeap> <a class="code" href="classandroid_1_1_camera_hardware_interface.html#9d4071fb234a0c2e7bf6ea78e723f2f4" title="Return the IMemoryHeap for the preview image heap.">getPreviewHeap</a>() <span class="keyword">const</span> = 0;
+<a name="l00085"></a>00085 <span class="comment"></span>
+<a name="l00086"></a>00086 <span class="comment"> /**</span>
+<a name="l00087"></a>00087 <span class="comment"> * Start preview mode. When a preview image is available</span>
+<a name="l00088"></a>00088 <span class="comment"> * preview_callback is called with the user parameter. The</span>
+<a name="l00089"></a>00089 <span class="comment"> * call back parameter may be null.</span>
+<a name="l00090"></a>00090 <span class="comment"> */</span>
+<a name="l00091"></a>00091 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_camera_hardware_interface.html#62def8031dee8bdab7933770708a6312" title="Start preview mode.">startPreview</a>(<a class="code" href="namespaceandroid.html#d32b08663d42356404e2eb971e271636" title="Callback for startPreview().">preview_callback</a> cb, <span class="keywordtype">void</span>* user) = 0;
+<a name="l00092"></a>00092 <span class="comment"></span>
+<a name="l00093"></a>00093 <span class="comment"> /**</span>
+<a name="l00094"></a>00094 <span class="comment"> * Stop a previously started preview.</span>
+<a name="l00095"></a>00095 <span class="comment"> */</span>
+<a name="l00096"></a>00096 <span class="keyword">virtual</span> <span class="keywordtype">void</span> <a class="code" href="classandroid_1_1_camera_hardware_interface.html#34faa77065f415b93cb1acf84fc788bf" title="Stop a previously started preview.">stopPreview</a>() = 0;
+<a name="l00097"></a>00097 <span class="comment"></span>
+<a name="l00098"></a>00098 <span class="comment"> /**</span>
+<a name="l00099"></a>00099 <span class="comment"> * Start auto focus, the callback routine is called</span>
+<a name="l00100"></a>00100 <span class="comment"> * once when focusing is complete. autoFocus() will</span>
+<a name="l00101"></a>00101 <span class="comment"> * be called again if another auto focus is needed.</span>
+<a name="l00102"></a>00102 <span class="comment"> */</span>
+<a name="l00103"></a>00103 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_camera_hardware_interface.html#0dda73938e9b18326dd48bd721dbd515" title="Start auto focus, the callback routine is called once when focusing is complete.">autoFocus</a>(<a class="code" href="namespaceandroid.html#4dca8d8b824ca9a684358133da0ec8f2" title="Callback for autoFocus().">autofocus_callback</a>,
+<a name="l00104"></a>00104 <span class="keywordtype">void</span>* user) = 0;
+<a name="l00105"></a>00105 <span class="comment"></span>
+<a name="l00106"></a>00106 <span class="comment"> /**</span>
+<a name="l00107"></a>00107 <span class="comment"> * Take a picture. The raw_callback is called when</span>
+<a name="l00108"></a>00108 <span class="comment"> * the uncompressed image is available. The jpeg_callback</span>
+<a name="l00109"></a>00109 <span class="comment"> * is called when the compressed image is available. These</span>
+<a name="l00110"></a>00110 <span class="comment"> * call backs may be null. The user parameter is passed</span>
+<a name="l00111"></a>00111 <span class="comment"> * to each of the call back routines.</span>
+<a name="l00112"></a>00112 <span class="comment"> */</span>
+<a name="l00113"></a>00113 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_camera_hardware_interface.html#2aedf65cad695ce439029f37a7cb66c4" title="Take a picture.">takePicture</a>(<a class="code" href="namespaceandroid.html#04c83209c2627e2d303320712ca9ee65" title="Callback for takePicture().">shutter_callback</a>,
+<a name="l00114"></a>00114 <a class="code" href="namespaceandroid.html#a97926709e452d66360cb9b24736969e" title="Callback for takePicture().">raw_callback</a>,
+<a name="l00115"></a>00115 <a class="code" href="namespaceandroid.html#c21980d4be1e0cc458399ecf5374d473" title="Callback for takePicture().">jpeg_callback</a>,
+<a name="l00116"></a>00116 <span class="keywordtype">void</span>* user) = 0;
+<a name="l00117"></a>00117 <span class="comment"></span>
+<a name="l00118"></a>00118 <span class="comment"> /**</span>
+<a name="l00119"></a>00119 <span class="comment"> * Cancel a picture that was started with takePicture. You may cancel any</span>
+<a name="l00120"></a>00120 <span class="comment"> * of the shutter, raw, or jpeg callbacks. Calling this method when no</span>
+<a name="l00121"></a>00121 <span class="comment"> * picture is being taken is a no-op.</span>
+<a name="l00122"></a>00122 <span class="comment"> */</span>
+<a name="l00123"></a>00123 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_camera_hardware_interface.html#da8faf376215a605357d26afa1b79386" title="Cancel a picture that was started with takePicture.">cancelPicture</a>(<span class="keywordtype">bool</span> cancel_shutter,
+<a name="l00124"></a>00124 <span class="keywordtype">bool</span> cancel_raw,
+<a name="l00125"></a>00125 <span class="keywordtype">bool</span> cancel_jpeg) = 0;
+<a name="l00126"></a>00126 <span class="comment"></span>
+<a name="l00127"></a>00127 <span class="comment"> /** Set the camera parameters. */</span>
+<a name="l00128"></a>00128 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_camera_hardware_interface.html#82e54ede14bd263274bbc8777bafc384" title="Set the camera parameters.">setParameters</a>(<span class="keyword">const</span> CameraParameters& params) = 0;
+<a name="l00129"></a>00129 <span class="comment"></span>
+<a name="l00130"></a>00130 <span class="comment"> /** Return the camera parameters. */</span>
+<a name="l00131"></a>00131 <span class="keyword">virtual</span> CameraParameters <a class="code" href="classandroid_1_1_camera_hardware_interface.html#4c748a3c0aa3c5f2333e0abcdbeb15cb" title="Return the camera parameters.">getParameters</a>() <span class="keyword">const</span> = 0;
+<a name="l00132"></a>00132 <span class="comment"></span>
+<a name="l00133"></a>00133 <span class="comment"> /**</span>
+<a name="l00134"></a>00134 <span class="comment"> * Release the hardware resources owned by this object. Note that this is</span>
+<a name="l00135"></a>00135 <span class="comment"> * *not* done in the destructor.</span>
+<a name="l00136"></a>00136 <span class="comment"> */</span>
+<a name="l00137"></a>00137 <span class="keyword">virtual</span> <span class="keywordtype">void</span> <a class="code" href="classandroid_1_1_camera_hardware_interface.html#df65310b8aa176e0ce5f08b87d6b7eb8" title="Release the hardware resources owned by this object.">release</a>() = 0;
+<a name="l00138"></a>00138 <span class="comment"></span>
+<a name="l00139"></a>00139 <span class="comment"> /**</span>
+<a name="l00140"></a>00140 <span class="comment"> * Dump state of the camera hardware</span>
+<a name="l00141"></a>00141 <span class="comment"> */</span>
+<a name="l00142"></a>00142 <span class="keyword">virtual</span> status_t <a class="code" href="classandroid_1_1_camera_hardware_interface.html#06df1bf91b8af07964dca314a6031b32" title="Dump state of the camera hardware.">dump</a>(<span class="keywordtype">int</span> fd, <span class="keyword">const</span> Vector<String16>& args) <span class="keyword">const</span> = 0;
+<a name="l00143"></a>00143 };
+<a name="l00144"></a>00144 <span class="comment"></span>
+<a name="l00145"></a>00145 <span class="comment">/** factory function to instantiate a camera hardware object */</span>
+<a name="l00146"></a>00146 <span class="keyword">extern</span> <span class="stringliteral">"C"</span> sp<CameraHardwareInterface> <a class="code" href="namespaceandroid.html#24c243f7f9ba0d1d881be17ae06254a2" title="factory function to instantiate a camera hardware object">openCameraHardware</a>();
+<a name="l00147"></a>00147
+<a name="l00148"></a>00148 }; <span class="comment">// namespace android</span>
+<a name="l00149"></a>00149
+<a name="l00150"></a>00150 <span class="preprocessor">#endif</span>
+</pre></div></div>
+</body>
+</html>
diff --git a/pdk/docs/_camera_hardware_interface_8h.html b/pdk/docs/_camera_hardware_interface_8h.html
new file mode 100755
index 0000000..633461f
--- /dev/null
+++ b/pdk/docs/_camera_hardware_interface_8h.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li class="current"><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+<h1>CameraHardwareInterface.h File Reference</h1>
+<p>
+<a href="_camera_hardware_interface_8h-source.html">Go to the source code of this file.</a><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Namespaces</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">namespace </td><td class="memItemRight" valign="bottom"><a class="el" href="namespaceandroid.html">android</a></td></tr>
+
+<tr><td colspan="2"><br><h2>Data Structures</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">class </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_camera_hardware_interface.html">android::CameraHardwareInterface</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight"><a class="el" href="_camera_hardware_interface_8h.html">CameraHardwareInterface.h</a> defines the interface to the camera hardware abstraction layer, used for setting and getting parameters, live previewing, and taking pictures. <a href="classandroid_1_1_camera_hardware_interface.html#_details">More...</a><br></td></tr>
+<tr><td colspan="2"><br><h2>Typedefs</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef void(* </td><td class="memItemRight" valign="bottom"><a class="el" href="namespaceandroid.html#d32b08663d42356404e2eb971e271636">android::preview_callback</a> )(const sp< IMemory > &mem, void *user)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Callback for startPreview(). <a href="#d32b08663d42356404e2eb971e271636"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef void(* </td><td class="memItemRight" valign="bottom"><a class="el" href="namespaceandroid.html#04c83209c2627e2d303320712ca9ee65">android::shutter_callback</a> )(void *user)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Callback for takePicture(). <a href="#04c83209c2627e2d303320712ca9ee65"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef void(* </td><td class="memItemRight" valign="bottom"><a class="el" href="namespaceandroid.html#a97926709e452d66360cb9b24736969e">android::raw_callback</a> )(const sp< IMemory > &mem, void *user)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Callback for takePicture(). <a href="#a97926709e452d66360cb9b24736969e"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef void(* </td><td class="memItemRight" valign="bottom"><a class="el" href="namespaceandroid.html#c21980d4be1e0cc458399ecf5374d473">android::jpeg_callback</a> )(const sp< IMemory > &mem, void *user)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Callback for takePicture(). <a href="#c21980d4be1e0cc458399ecf5374d473"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef void(* </td><td class="memItemRight" valign="bottom"><a class="el" href="namespaceandroid.html#4dca8d8b824ca9a684358133da0ec8f2">android::autofocus_callback</a> )(bool focused, void *user)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Callback for autoFocus(). <a href="#4dca8d8b824ca9a684358133da0ec8f2"></a><br></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">sp< CameraHardwareInterface > </td><td class="memItemRight" valign="bottom"><a class="el" href="namespaceandroid.html#24c243f7f9ba0d1d881be17ae06254a2">android::openCameraHardware</a> ()</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">factory function to instantiate a camera hardware object <a href="#24c243f7f9ba0d1d881be17ae06254a2"></a><br></td></tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/androidBluetooth.gif b/pdk/docs/androidBluetooth.gif
new file mode 100755
index 0000000..e62f5a8
--- /dev/null
+++ b/pdk/docs/androidBluetooth.gif
Binary files differ
diff --git a/pdk/docs/androidBluetoothProcessDiagram.jpg b/pdk/docs/androidBluetoothProcessDiagram.jpg
new file mode 100755
index 0000000..6872180
--- /dev/null
+++ b/pdk/docs/androidBluetoothProcessDiagram.jpg
Binary files differ
diff --git a/pdk/docs/androidCameraArchitecture.gif b/pdk/docs/androidCameraArchitecture.gif
new file mode 100755
index 0000000..2679b43
--- /dev/null
+++ b/pdk/docs/androidCameraArchitecture.gif
Binary files differ
diff --git a/pdk/docs/annotated.html b/pdk/docs/annotated.html
new file mode 100755
index 0000000..c8ea2e2
--- /dev/null
+++ b/pdk/docs/annotated.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li class="current"><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li class="current"><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="functions.html"><span>Data Fields</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+<h1>Data Structures</h1>Here are the data structures with brief descriptions:<table>
+ <tr><td class="indexkey"><a class="el" href="classandroid_1_1_audio_hardware_interface.html">android::AudioHardwareInterface</a></td><td class="indexvalue"><a class="el" href="_audio_hardware_interface_8h.html">AudioHardwareInterface.h</a> defines the interface to the audio hardware abstraction layer </td></tr>
+ <tr><td class="indexkey"><a class="el" href="classandroid_1_1_audio_stream_in.html">android::AudioStreamIn</a></td><td class="indexvalue"><a class="el" href="classandroid_1_1_audio_stream_in.html" title="AudioStreamIn is the abstraction interface for the audio input hardware.">AudioStreamIn</a> is the abstraction interface for the audio input hardware </td></tr>
+ <tr><td class="indexkey"><a class="el" href="classandroid_1_1_audio_stream_out.html">android::AudioStreamOut</a></td><td class="indexvalue"><a class="el" href="classandroid_1_1_audio_stream_out.html" title="AudioStreamOut is the abstraction interface for the audio output hardware.">AudioStreamOut</a> is the abstraction interface for the audio output hardware </td></tr>
+ <tr><td class="indexkey"><a class="el" href="classandroid_1_1_camera_hardware_interface.html">android::CameraHardwareInterface</a></td><td class="indexvalue"><a class="el" href="_camera_hardware_interface_8h.html">CameraHardwareInterface.h</a> defines the interface to the camera hardware abstraction layer, used for setting and getting parameters, live previewing, and taking pictures </td></tr>
+ <tr><td class="indexkey"><a class="el" href="struct_gps_callbacks.html">GpsCallbacks</a></td><td class="indexvalue">GPS callback structure </td></tr>
+ <tr><td class="indexkey"><a class="el" href="struct_gps_interface.html">GpsInterface</a></td><td class="indexvalue">Represents the standard GPS interface </td></tr>
+ <tr><td class="indexkey"><a class="el" href="struct_gps_location.html">GpsLocation</a></td><td class="indexvalue">Represents a location </td></tr>
+ <tr><td class="indexkey"><a class="el" href="struct_gps_status.html">GpsStatus</a></td><td class="indexvalue">Represents the status </td></tr>
+ <tr><td class="indexkey"><a class="el" href="struct_gps_supl_interface.html">GpsSuplInterface</a></td><td class="indexvalue">Extended interface for SUPL support </td></tr>
+ <tr><td class="indexkey"><a class="el" href="struct_gps_sv_info.html">GpsSvInfo</a></td><td class="indexvalue">Represents SV information </td></tr>
+ <tr><td class="indexkey"><a class="el" href="struct_gps_sv_status.html">GpsSvStatus</a></td><td class="indexvalue">Represents SV status </td></tr>
+ <tr><td class="indexkey"><a class="el" href="struct_gps_xtra_callbacks.html">GpsXtraCallbacks</a></td><td class="indexvalue">Callback structure for the XTRA interface </td></tr>
+ <tr><td class="indexkey"><a class="el" href="struct_gps_xtra_interface.html">GpsXtraInterface</a></td><td class="indexvalue">Extended interface for XTRA support </td></tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/audio_sub_system.html b/pdk/docs/audio_sub_system.html
index 8f72e38..e0cf217 100755
--- a/pdk/docs/audio_sub_system.html
+++ b/pdk/docs/audio_sub_system.html
@@ -2,11 +2,23 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
-<title>Android - Audio Subsystem</title>
+<title>Android - Porting Guide</title>
<script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=internal-codesite" type="text/javascript"></script>
<script src="http://code.google.com/js/jquery.js" type="text/javascript"></script>
<script type="text/javascript">var _tocPath_ = 'http://code.google.com/android/_toc.ezt';</script>
<script src="http://code.google.com/js/codesite.pack.01312008.js" type="text/javascript"></script>
+<script language="JavaScript">
+function resizeHeight() {
+ if(document.getElementById && !(document.all)) {
+ height= document.getElementById('doxygen').contentDocument.body.scrollHeight + 20;
+ document.getElementById('doxygen').style.height = height;
+ }
+ else if(document.all) {
+ height= document.frames('doxygen').document.body.scrollHeight + 20;
+ document.all.doxygen.style.height = height;
+ }
+}
+</script>
<link href="http://code.google.com/css/codesite.pack.01312008.css" type="text/css" rel="stylesheet">
</link>
@@ -33,6 +45,7 @@
<div id="skipto"> </div>
<div id="langpref">
<!--<a class="dropdown" href="/">English</a> <span>|</span> <a href="/more/">Site Directory</a> -->
+
</div>
<div id="gc-header">
<div id="logo"><a href="http://code.google.com/android/index.html"><img src="http://code.google.com/android/images/logo_android.gif" alt="Android"/></a></div>
@@ -51,6 +64,7 @@
}
</style>
</noscript>
+
<div id="searchForm2" class="searchForm2" style="display:none">
<form id="searchbox_001456098540849067467:6whlsytkdqg" action="http://www.google.com/cse">
<input type="hidden" name="cx" value="001456098540849067467:6whlsytkdqg" />
@@ -59,6 +73,7 @@
<input type="submit" name="sa" value="Search" title="Search"/>
<br/>
<div class="greytext">e.g. "ajax apis" or "open source"</div>
+
</form>
</div>
<!-- end searchForm2 -->
@@ -71,15 +86,18 @@
<div id="codesiteContent">
<a name="gc-topnav-anchor"></a>
<div id="gc-topnav">
+
<h1>Android Platform Development Kit</h1>
<ul class="gc-topnav-tabs">
<li id="sdk_link"> <a href="http://code.google.com/android/index.html" title="Android Software Development Kit">SDK</a> </li>
<li id="docs_link"> <a href="index.html" title="Official Android documentation">Docs</a> </li>
<li id="faq_link"> <a href="http://code.google.com/android/kb/index.html" title="Answers to frequently asked questions about Android">FAQ</a> </li>
+
<li> <a href="http://android-developers.blogspot.com/" title="Official Android blog">Blog</a> </li>
<li> <a href="http://code.google.com/android/groups.html" title="Android developer forum">Group</a> </li>
<li> <a href="http://code.google.com/android/terms.html" title="Android terms of service">Terms</a> </li>
- <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20audio_sub_system.html%20v0.3%20-%209%20June%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+ <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20audio_sub_system.html%20v0.6%20-%2025%20November%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+
</ul>
</div>
<!-- end gc-topnav -->
@@ -91,19 +109,18 @@
<h1><a href="index.html">Documentation</a></h1>
<ul>
<li> <strong>Introduction</strong>
+
<ul>
<li><a href="system_requirements.html">Device Requirements</a></li>
</ul>
</li>
<li> <strong>Dev Environment Setup</strong>
<ul>
- <li><a href="source_setup_guide.html">Host System Setup</a></li>
- <li><a href="getting_source_code.html">Getting Source Code</a></li>
- <li> <a href="intro_source_code.html">Source Code Overview</a></li>
<li><a href="build_system.html">Build System</a></li>
</ul>
</li>
<li> <strong>Basic Bring up</strong>
+
<ul>
<li><a href="build_new_device.html">Building New Device</a></li>
<li><a href="bring_up.html">Bring up</a></li>
@@ -111,26 +128,39 @@
<li><a href="display_drivers.html">Display Drivers</a></li>
</ul>
</li>
+
<li> <strong>Multimedia</strong>
<ul>
- <li><a href="audio_sub_system.html">Audio Subsystem</a></li>
+ <li><a href="audio_sub_system.html">Audio</a></li>
+ <li><a href="camera.html">Camera</a></li>
</ul>
</li>
<li> <strong>Power Management</strong>
+
<ul>
<li><a href="power_management.html">Power Management</a></li>
</ul>
</li>
+
+ <li> <strong>Networking</strong>
+ <ul>
+ <li><a href="wifi.html">Wi-Fi</a></li>
+ <li><a href="gps.html">GPS</a></li>
+ <li><a href="bluetooth.html">Bluetooth</a></li>
+ </ul>
+ </li>
+
<li> <strong>Telephony</strong>
<ul>
<li><a href="telephony.html">Radio Interface Layer</a></li>
+
</ul>
</li>
<li> <strong>Testing</strong>
<ul>
- <li><a href="instrumentation_framework.html">Instrumentation Framework</a></li>
<li><a href="instrumentation_testing.html">Instrumentation Testing</a></li>
</ul>
+
</li>
</ul>
</li>
@@ -142,78 +172,64 @@
<div class="jd-descr">
-<a name="androidAudioSubSystemTitle"></a><h1>Audio Subsystem</h1>
+<a name="androidAudioSubSystemTitle"></a><h1>Audio</h1>
<a name="toc"/>
<div style="padding:10px">
<a href="#androidAudioSubSystemIntroduction">Introduction</a><br/>
-<a href="#androidAudioSubSystemPorting">Porting Android to other Audio Stacks</a><br/><div style="padding-left:40px">
-
-<a href="#androidAudioSubSystemAbstract">AudioHardwareInterface Abstract Class</a><br/>
-<a href="#androidAudioSubSystemAudioHardwareInterfaceModification">Modifying AudioHardwareInterface</a><br/></div></div></font></div>
+<a href="#androidAudioBuildingDriver">Building an Audio Library</a><br/>
+<a href="#androidAudioInterface">Interface</a><br/></div></font></div>
<a name="androidAudioSubSystemIntroduction"></a><h2>Introduction</h2>
-<p>Android provides two native layers that handle audio software:</p>
-<p><ul><li><b>Audio Flinger</b>: the audio software implementation that provides the minimum required audio functions (as illustrated in the diagram below).</li>
-<li><b>AudioHardwareInterface</b>: the hardware abstraction layer that hides driver-specific audio implementations from the Android platform.</li>
-</ul>
-</p>
+<p>AudioHardwareInterface serves as the glue between proprietary audio drivers and the Android AudioFlinger service, the core audio service that handles all audio-related requests from applications.</p>
<p><img src="android_audio_architecture.gif"></p>
-Solid elements represent Android blocks and dashed elements represent partner-specific proprietary blocks.
+Solid elements represent Android blocks and dashed elements represent partner-specific blocks.
-<a name="androidAudioSubSystemPorting"></a><h2>Porting Android to other Audio Stacks</h2>
+<a name="androidAudioBuildingDriver"></a><h2>Building an Audio Library</h2>
-<p>Porting Android to other audio stacks (OSS, ALSA, proprietary user-space audio libraries, etc.) requires inheriting from and modifying <code>AudioHardwareInterface</code> to support the driver-specific implementation.</p>
+<p>To implement an audio driver, create a shared library that implements the interface defined in <code>AudioHardwareInterface.h</code>. You must name your shared library <code>libaudio.so</code> so that it will get loaded from <code>/system/lib</code> at runtime. Place libaudio sources and <code>Android.mk</code> in <code>partner/acme/chipset_or_board/libaudio/</code>.</p>
+<p>The following stub <code>Android.mk</code> file ensures that <code>libaudio</code> compiles and links to the appropriate libraries:</p>
-
-<a name="androidAudioSubSystemAbstract"></a><h3>AudioHardwareInterface Abstract Class</h3>
-
-<p><code>AudioHardwareInterface</code> (<code>//device/servers/audio/flinger</code>) contains several pure virtual functions that the audio driver class being ported needs to implement.</p>
-
-
-<a name="androidAudioSubSystemAudioHardwareInterfaceModification"></a><h3>Modifying AudioHardwareInterface</h3>
-
-<p>Once the audio driver that inherits <code>AudioHardwareInterface</code> is ready, modify the static function <code>AudioHardwareInterface::create()</code> in order to link/load the driver in Android.</p>
-
-
-<p>Assume the manufacturer audio driver inherits from <code>AudioHarddwareInterface</code> and that it is compiled into a native shared library (<code>libaudio.so</code>). In this case, use <code>dlopen</code> to load the library.</p>
-<p>You can find an example of a similar implementation in <code>//device/libs/media/mediaplayer.cpp</code>. (Note that the example below uses <code>libpv.so</code> because this is a real code snippet from <code>mediaplayer.cpp</code>. If your native shared library is called <code>libaudio.so</code>, replace <code>libpv.so</code> with your <code>libaudio.so</code>.)
-<pre box="prettify">
-// load PV library and create PV player
-mLibHandle = dlopen("libpv.so", RTLD_NOW);
-if (!mLibHandle) {
- LOGE("dlopen failed on libpv.so\n");
- return UNKNOWN_ERROR;
-}
-createPlayer_f createPlayer = reinterpret_cast<createPlayer_f>(dlsym(mLibHandle, "createPlayer"));
-if (!createPlayer) {
- LOGE("dlsym failed on createPlayer in libpv.so\n");
- return UNKNOWN_ERROR;
-}
-</pre>
-<p>Load the libraries with a call from <code>AudioHardwareInterface::create()</code>, as illustrated below (full code found in <code>//device/servers/audioflinger</code>).</p>
<pre class="prettify">
-if (property_get("ro.kernel.qemu", value, 0)) {
- LOGD("Running in emulation - using generic audio driver");
- hw = new AudioHardwareGeneric();
-}
-else {
- // Insert calling of dynamic loading of driver here...
-}
-if (hw->initCheck() != NO_ERROR) {
- LOGW("Using stubbed audio hardware. No sound will be produced.");
- delete hw;
- hw = new AudioHardwareStub();
-}
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libaudio
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libutils \
+ libmedia \
+ libhardware
+
+LOCAL_SRC_FILES += MyAudioHardware.cpp
+
+LOCAL_CFLAGS +=
+
+LOCAL_C_INCLUDES +=
+
+LOCAL_STATIC_LIBRARIES += libaudiointerface
+
+include $(BUILD_SHARED_LIBRARY)
</pre>
+<a name="androidAudioInterface"></a><h2>Interface</h2>
+
+
+
+<p class="note"><strong>Note</strong>: This document relies on some Doxygen-generated content that appears in an iFrame below. To return to the Doxygen default content for this page, <a href="audio_sub_system.html">click here</a>.</p>
+
+
+<iframe onLoad="resizeHeight();" src="_audio_hardware_interface_8h.html" scrolling="no" scroll="no" id="doxygen" marginwidth="0" marginheight="0" frameborder="0" style="width:100%;"></iframe>
+
+
<p><span class="lh2"><a name="androidFooter"></a></span>
</div>
@@ -239,7 +255,7 @@
pageTracker._trackPageview();
} catch(e) {}
</script>
-<div id="jd-build-id"> v0.3 - 9 June 2008</div>
+<div id="jd-build-id"> v0.6 - 25 November 2008</div>
</div></div></div></body>
</html>
diff --git a/pdk/docs/bluetooth.html b/pdk/docs/bluetooth.html
new file mode 100755
index 0000000..edd3c26
--- /dev/null
+++ b/pdk/docs/bluetooth.html
@@ -0,0 +1,276 @@
+
+<p><span class="lh2"><a name="androidHeader"></a></span>
+
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
+<title>Android - Porting Guide</title>
+<script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=internal-codesite" type="text/javascript"></script>
+<script src="http://code.google.com/js/jquery.js" type="text/javascript"></script>
+<script type="text/javascript">var _tocPath_ = 'http://code.google.com/android/_toc.ezt';</script>
+<script src="http://code.google.com/js/codesite.pack.01312008.js" type="text/javascript"></script>
+<script language="JavaScript">
+function resizeHeight() {
+ if(document.getElementById && !(document.all)) {
+ height= document.getElementById('doxygen').contentDocument.body.scrollHeight + 20;
+ document.getElementById('doxygen').style.height = height;
+ }
+ else if(document.all) {
+ height= document.frames('doxygen').document.body.scrollHeight + 20;
+ document.all.doxygen.style.height = height;
+ }
+}
+</script>
+<link href="http://code.google.com/css/codesite.pack.01312008.css" type="text/css" rel="stylesheet">
+</link>
+
+<!--[if IE]><link rel="stylesheet" type="text/css" href="/css/iehacks.css" /><![endif]-->
+<script src="http://code.google.com/android/assets/search_autocomplete.js"></script>
+<link rel="stylesheet" type="text/css" href="http://code.google.com/css/semantic_headers.css" />
+<link rel="stylesheet" type="text/css" href="http://code.google.com/android/assets/style.css" />
+<script>
+ jQuery(document).ready(function() {
+ jQuery("pre").addClass("prettyprint");
+ });
+ </script>
+<style type="text/css">
+<!--
+h1,h2,h3 {
+ color: #000000;
+}
+-->
+</style>
+</head>
+<body class="gc-documentation">
+<div id="gc-container">
+<a name="top"></a>
+<div id="skipto"> </div>
+<div id="langpref">
+ <!--<a class="dropdown" href="/">English</a> <span>|</span> <a href="/more/">Site Directory</a> -->
+
+</div>
+<div id="gc-header">
+ <div id="logo"><a href="http://code.google.com/android/index.html"><img src="http://code.google.com/android/images/logo_android.gif" alt="Android"/></a></div>
+ <div id="search" style="inline">
+ <div id="searchForm" class="searchForm" style="height: 44px;">
+ <!--previously form was here-->
+ </div>
+ <!-- end searchForm -->
+ <noscript>
+ <style type="text/css">
+ .searchForm {
+ display : none !important;
+ }
+ .searchForm2 {
+ display : inline !important;
+ }
+ </style>
+ </noscript>
+
+ <div id="searchForm2" class="searchForm2" style="display:none">
+ <form id="searchbox_001456098540849067467:6whlsytkdqg" action="http://www.google.com/cse">
+ <input type="hidden" name="cx" value="001456098540849067467:6whlsytkdqg" />
+ <input type="hidden" name="cof" value="FORID:0" />
+ <input type="text" name="q" maxlength="2048" size="41" autocomplete="off" title="Google Code Search"/>
+ <input type="submit" name="sa" value="Search" title="Search"/>
+ <br/>
+ <div class="greytext">e.g. "ajax apis" or "open source"</div>
+
+ </form>
+ </div>
+ <!-- end searchForm2 -->
+ </div>
+ <!-- end search -->
+</div>
+<!-- end gc-header -->
+<div id="searchControl" class="search-control"></div>
+<!--[if IE]><iframe id="backiFrame" name="backiFrame" src='/dummy.html' style="display:none"></iframe><![endif]-->
+<div id="codesiteContent">
+<a name="gc-topnav-anchor"></a>
+<div id="gc-topnav">
+
+ <h1>Android Platform Development Kit</h1>
+ <ul class="gc-topnav-tabs">
+ <li id="sdk_link"> <a href="http://code.google.com/android/index.html" title="Android Software Development Kit">SDK</a> </li>
+ <li id="docs_link"> <a href="index.html" title="Official Android documentation">Docs</a> </li>
+ <li id="faq_link"> <a href="http://code.google.com/android/kb/index.html" title="Answers to frequently asked questions about Android">FAQ</a> </li>
+
+ <li> <a href="http://android-developers.blogspot.com/" title="Official Android blog">Blog</a> </li>
+ <li> <a href="http://code.google.com/android/groups.html" title="Android developer forum">Group</a> </li>
+ <li> <a href="http://code.google.com/android/terms.html" title="Android terms of service">Terms</a> </li>
+ <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20bluetooth.html%20v0.6%20-%2025%20November%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+
+ </ul>
+</div>
+<!-- end gc-topnav -->
+<div class="g-section g-tpl-180">
+<a name="gc-toc"></a>
+<div class="g-unit g-first" id="gc-toc">
+ <ul>
+ <li>
+ <h1><a href="index.html">Documentation</a></h1>
+ <ul>
+ <li> <strong>Introduction</strong>
+
+ <ul>
+ <li><a href="system_requirements.html">Device Requirements</a></li>
+ </ul>
+ </li>
+ <li> <strong>Dev Environment Setup</strong>
+ <ul>
+ <li><a href="build_system.html">Build System</a></li>
+ </ul>
+ </li>
+ <li> <strong>Basic Bring up</strong>
+
+ <ul>
+ <li><a href="build_new_device.html">Building New Device</a></li>
+ <li><a href="bring_up.html">Bring up</a></li>
+ <li><a href="keymaps_keyboard_input.html">Keymaps and Keyboard</a></li>
+ <li><a href="display_drivers.html">Display Drivers</a></li>
+ </ul>
+ </li>
+
+ <li> <strong>Multimedia</strong>
+ <ul>
+ <li><a href="audio_sub_system.html">Audio</a></li>
+ <li><a href="camera.html">Camera</a></li>
+ </ul>
+ </li>
+ <li> <strong>Power Management</strong>
+
+ <ul>
+ <li><a href="power_management.html">Power Management</a></li>
+ </ul>
+ </li>
+
+ <li> <strong>Networking</strong>
+ <ul>
+ <li><a href="wifi.html">Wi-Fi</a></li>
+ <li><a href="gps.html">GPS</a></li>
+ <li><a href="bluetooth.html">Bluetooth</a></li>
+ </ul>
+ </li>
+
+ <li> <strong>Telephony</strong>
+ <ul>
+ <li><a href="telephony.html">Radio Interface Layer</a></li>
+
+ </ul>
+ </li>
+ <li> <strong>Testing</strong>
+ <ul>
+ <li><a href="instrumentation_testing.html">Instrumentation Testing</a></li>
+ </ul>
+
+ </li>
+ </ul>
+ </li>
+ </ul>
+</div>
+<a name="gc-pagecontent"></a>
+<div class="g-unit" id="gc-pagecontent">
+<div id="jd-content">
+<div class="jd-descr">
+
+
+<a name="androidBluetoothTitle"></a><h1>Bluetooth</h1>
+
+
+
+<a name="toc"/>
+<div style="padding:10px">
+<a href="#androidBluetoothIntro">Introduction</a><br/>
+<a href="#androidBluetoothPorting">Porting</a><br/><div style="padding-left:40px">
+
+<a href="#androidBluetoothPortingDriver">UART Driver</a><br/>
+<a href="#androidBluetoothPortingPowerOnOff">Bluetooth Power On / Off</a><br/></div>
+<a href="#androidBluetoothTools">Tools</a><br/></div></font></div>
+
+<a name="androidBluetoothIntro"></a><h2>Introduction</h2>
+
+<p>Android's Bluetooth stack uses BlueZ version 3.36 for GAP, SDP, and RFCOMM profiles, and is a SIG-qualified Bluetooth 2.0 host stack.</p>
+
+<p>Bluez is GPL licensed, so the Android framework interacts with userspace bluez code through D-BUS IPC to avoid proprietary code.</p>
+
+<p>Headset and Handsfree (v1.5) profiles are implemented in the Android framework and are both tightly coupled with the Phone App. These profiles are also SIG qualified.</p>
+
+<p>The diagram below offers a library-oriented view of the Bluetooth stack. Click <a href="bluetooth_process.html">Bluetooth Process Diagram</a> for a process-oriented view.</p>
+
+<p><img src="androidBluetooth.gif"></p>
+
+Solid elements represent Android blocks and dashed elements represent partner-specific blocks.
+
+
+
+<a name="androidBluetoothPorting"></a><h2>Porting</h2>
+
+<p>BlueZ is Bluetooth 2.0 compatible and should work with any 2.0 chipset. There are two integration points:</p>
+<p><ul>
+<li>UART driver</li>
+<li>Bluetooth Power On / Off</li>
+</ul>
+</p>
+
+
+<a name="androidBluetoothPortingDriver"></a><h3>UART Driver</h3>
+
+<p>The BlueZ kernel sub-system attaches to your hardware-specific UART driver using the <code>hciattach</code> daemon.</p>
+<p>For example, for MSM7201A, this is <code>drivers/serial/msm_serial.c</code>. You may also need to edit command line options to <code>hciattach</code> via <code>init.rc</code>.</p>
+
+
+<a name="androidBluetoothPortingPowerOnOff"></a><h3>Bluetooth Power On / Off</h3>
+
+<p>The method for powering on and off your bluetooth chip varies from Android V 1.0 to post 1.0.</p>
+
+<p><ul>
+<li><b>1.0</b>: Android framework writes a 0 or 1 to <code>/sys/modules/board_[PLATFORM]/parameters/bluetooth_power_on</code>.</li>
+
+<li><b>Post 1.0</b>: Android framework uses the linux <code>rfkill</code> API. See <code>arch/arm/mach-msm/board-trout-rfkill.c</code> for an example.</li>
+</ul>
+</p>
+
+
+<a name="androidBluetoothTools"></a><h2>Tools</h2>
+
+<p>BlueZ provides a rich set of command line tools for debugging and interacting with the Bluetooth sub-system, including:</p>
+<p><ul>
+<li><code>hciconfig</code></li>
+<li><code>hcitool</code></li>
+<li><code>hcidump</code></li>
+<li><code>sdptool</code></li>
+<li><code>dbus-send</code></li>
+<li><code>dbus-monitor</code></li>
+</ul>
+</p>
+
+
+<p><span class="lh2"><a name="androidFooter"></a></span>
+
+ </div>
+ </div>
+ <!-- end gc-pagecontent -->
+ </div>
+ <!-- end gooey wrapper -->
+ </div>
+ <!-- end codesearchresults -->
+ <div id="gc-footer" dir="ltr">
+ <div class="text"> ©2008 Google<!-- - <a href="/">Code Home</a> - <a href="http://www.google.com/accounts/TOS">Site Terms of Service</a> - <a href="http://www.google.com/privacy.html">Privacy Policy</a> - <a href="/more">Site Directory</a> --></div>
+ </div>
+ <!-- end gc-footer -->
+</div>
+<!-- end gc-containter -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-18071-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+<div id="jd-build-id"> v0.6 - 25 November 2008</div>
+</div></div></div></body>
+</html>
+
diff --git a/pdk/docs/bring_up.html b/pdk/docs/bring_up.html
index f53474a..b70a35d 100755
--- a/pdk/docs/bring_up.html
+++ b/pdk/docs/bring_up.html
@@ -2,11 +2,23 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
-<title>Android - Bring Up</title>
+<title>Android - Porting Guide</title>
<script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=internal-codesite" type="text/javascript"></script>
<script src="http://code.google.com/js/jquery.js" type="text/javascript"></script>
<script type="text/javascript">var _tocPath_ = 'http://code.google.com/android/_toc.ezt';</script>
<script src="http://code.google.com/js/codesite.pack.01312008.js" type="text/javascript"></script>
+<script language="JavaScript">
+function resizeHeight() {
+ if(document.getElementById && !(document.all)) {
+ height= document.getElementById('doxygen').contentDocument.body.scrollHeight + 20;
+ document.getElementById('doxygen').style.height = height;
+ }
+ else if(document.all) {
+ height= document.frames('doxygen').document.body.scrollHeight + 20;
+ document.all.doxygen.style.height = height;
+ }
+}
+</script>
<link href="http://code.google.com/css/codesite.pack.01312008.css" type="text/css" rel="stylesheet">
</link>
@@ -33,6 +45,7 @@
<div id="skipto"> </div>
<div id="langpref">
<!--<a class="dropdown" href="/">English</a> <span>|</span> <a href="/more/">Site Directory</a> -->
+
</div>
<div id="gc-header">
<div id="logo"><a href="http://code.google.com/android/index.html"><img src="http://code.google.com/android/images/logo_android.gif" alt="Android"/></a></div>
@@ -51,6 +64,7 @@
}
</style>
</noscript>
+
<div id="searchForm2" class="searchForm2" style="display:none">
<form id="searchbox_001456098540849067467:6whlsytkdqg" action="http://www.google.com/cse">
<input type="hidden" name="cx" value="001456098540849067467:6whlsytkdqg" />
@@ -59,6 +73,7 @@
<input type="submit" name="sa" value="Search" title="Search"/>
<br/>
<div class="greytext">e.g. "ajax apis" or "open source"</div>
+
</form>
</div>
<!-- end searchForm2 -->
@@ -71,15 +86,18 @@
<div id="codesiteContent">
<a name="gc-topnav-anchor"></a>
<div id="gc-topnav">
+
<h1>Android Platform Development Kit</h1>
<ul class="gc-topnav-tabs">
<li id="sdk_link"> <a href="http://code.google.com/android/index.html" title="Android Software Development Kit">SDK</a> </li>
<li id="docs_link"> <a href="index.html" title="Official Android documentation">Docs</a> </li>
<li id="faq_link"> <a href="http://code.google.com/android/kb/index.html" title="Answers to frequently asked questions about Android">FAQ</a> </li>
+
<li> <a href="http://android-developers.blogspot.com/" title="Official Android blog">Blog</a> </li>
<li> <a href="http://code.google.com/android/groups.html" title="Android developer forum">Group</a> </li>
<li> <a href="http://code.google.com/android/terms.html" title="Android terms of service">Terms</a> </li>
- <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20bring_up.html%20v0.3%20-%209%20June%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+ <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20bring_up.html%20v0.6%20-%2025%20November%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+
</ul>
</div>
<!-- end gc-topnav -->
@@ -91,19 +109,18 @@
<h1><a href="index.html">Documentation</a></h1>
<ul>
<li> <strong>Introduction</strong>
+
<ul>
<li><a href="system_requirements.html">Device Requirements</a></li>
</ul>
</li>
<li> <strong>Dev Environment Setup</strong>
<ul>
- <li><a href="source_setup_guide.html">Host System Setup</a></li>
- <li><a href="getting_source_code.html">Getting Source Code</a></li>
- <li> <a href="intro_source_code.html">Source Code Overview</a></li>
<li><a href="build_system.html">Build System</a></li>
</ul>
</li>
<li> <strong>Basic Bring up</strong>
+
<ul>
<li><a href="build_new_device.html">Building New Device</a></li>
<li><a href="bring_up.html">Bring up</a></li>
@@ -111,26 +128,39 @@
<li><a href="display_drivers.html">Display Drivers</a></li>
</ul>
</li>
+
<li> <strong>Multimedia</strong>
<ul>
- <li><a href="audio_sub_system.html">Audio Subsystem</a></li>
+ <li><a href="audio_sub_system.html">Audio</a></li>
+ <li><a href="camera.html">Camera</a></li>
</ul>
</li>
<li> <strong>Power Management</strong>
+
<ul>
<li><a href="power_management.html">Power Management</a></li>
</ul>
</li>
+
+ <li> <strong>Networking</strong>
+ <ul>
+ <li><a href="wifi.html">Wi-Fi</a></li>
+ <li><a href="gps.html">GPS</a></li>
+ <li><a href="bluetooth.html">Bluetooth</a></li>
+ </ul>
+ </li>
+
<li> <strong>Telephony</strong>
<ul>
<li><a href="telephony.html">Radio Interface Layer</a></li>
+
</ul>
</li>
<li> <strong>Testing</strong>
<ul>
- <li><a href="instrumentation_framework.html">Instrumentation Framework</a></li>
<li><a href="instrumentation_testing.html">Instrumentation Testing</a></li>
</ul>
+
</li>
</ul>
</li>
@@ -172,7 +202,6 @@
</ul>
<p> </p>
<h3>4. Burn Images to Flash</h3>
-<p>### NEED HELP FINISHING THIS SECTION. KERNEL AND RAMDISK DON'T BELONG IN THIS LIST. </p>
<p>An image represents the state of a system or part of a system stored in non-volatile memory. The build process should produce the following system images:</p>
<ul>
<li><strong>bootloader</strong>: The bootloader is a small program responsible for initiating loading of the operating system. </li>
@@ -526,7 +555,7 @@
pageTracker._trackPageview();
} catch(e) {}
</script>
-<div id="jd-build-id"> v0.3 - 9 June 2008</div>
+<div id="jd-build-id"> v0.6 - 25 November 2008</div>
</div></div></div></body>
</html>
diff --git a/pdk/docs/build_new_device.html b/pdk/docs/build_new_device.html
index bc5294a..cbf9ed7 100755
--- a/pdk/docs/build_new_device.html
+++ b/pdk/docs/build_new_device.html
@@ -2,11 +2,23 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
-<title>Android - Building Android for a new Mobile Device</title>
+<title>Android - Porting Guide</title>
<script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=internal-codesite" type="text/javascript"></script>
<script src="http://code.google.com/js/jquery.js" type="text/javascript"></script>
<script type="text/javascript">var _tocPath_ = 'http://code.google.com/android/_toc.ezt';</script>
<script src="http://code.google.com/js/codesite.pack.01312008.js" type="text/javascript"></script>
+<script language="JavaScript">
+function resizeHeight() {
+ if(document.getElementById && !(document.all)) {
+ height= document.getElementById('doxygen').contentDocument.body.scrollHeight + 20;
+ document.getElementById('doxygen').style.height = height;
+ }
+ else if(document.all) {
+ height= document.frames('doxygen').document.body.scrollHeight + 20;
+ document.all.doxygen.style.height = height;
+ }
+}
+</script>
<link href="http://code.google.com/css/codesite.pack.01312008.css" type="text/css" rel="stylesheet">
</link>
@@ -33,6 +45,7 @@
<div id="skipto"> </div>
<div id="langpref">
<!--<a class="dropdown" href="/">English</a> <span>|</span> <a href="/more/">Site Directory</a> -->
+
</div>
<div id="gc-header">
<div id="logo"><a href="http://code.google.com/android/index.html"><img src="http://code.google.com/android/images/logo_android.gif" alt="Android"/></a></div>
@@ -51,6 +64,7 @@
}
</style>
</noscript>
+
<div id="searchForm2" class="searchForm2" style="display:none">
<form id="searchbox_001456098540849067467:6whlsytkdqg" action="http://www.google.com/cse">
<input type="hidden" name="cx" value="001456098540849067467:6whlsytkdqg" />
@@ -59,6 +73,7 @@
<input type="submit" name="sa" value="Search" title="Search"/>
<br/>
<div class="greytext">e.g. "ajax apis" or "open source"</div>
+
</form>
</div>
<!-- end searchForm2 -->
@@ -71,15 +86,18 @@
<div id="codesiteContent">
<a name="gc-topnav-anchor"></a>
<div id="gc-topnav">
+
<h1>Android Platform Development Kit</h1>
<ul class="gc-topnav-tabs">
<li id="sdk_link"> <a href="http://code.google.com/android/index.html" title="Android Software Development Kit">SDK</a> </li>
<li id="docs_link"> <a href="index.html" title="Official Android documentation">Docs</a> </li>
<li id="faq_link"> <a href="http://code.google.com/android/kb/index.html" title="Answers to frequently asked questions about Android">FAQ</a> </li>
+
<li> <a href="http://android-developers.blogspot.com/" title="Official Android blog">Blog</a> </li>
<li> <a href="http://code.google.com/android/groups.html" title="Android developer forum">Group</a> </li>
<li> <a href="http://code.google.com/android/terms.html" title="Android terms of service">Terms</a> </li>
- <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20build_new_device.html%20v0.3%20-%209%20June%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+ <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20build_new_device.html%20v0.6%20-%2025%20November%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+
</ul>
</div>
<!-- end gc-topnav -->
@@ -91,19 +109,18 @@
<h1><a href="index.html">Documentation</a></h1>
<ul>
<li> <strong>Introduction</strong>
+
<ul>
<li><a href="system_requirements.html">Device Requirements</a></li>
</ul>
</li>
<li> <strong>Dev Environment Setup</strong>
<ul>
- <li><a href="source_setup_guide.html">Host System Setup</a></li>
- <li><a href="getting_source_code.html">Getting Source Code</a></li>
- <li> <a href="intro_source_code.html">Source Code Overview</a></li>
<li><a href="build_system.html">Build System</a></li>
</ul>
</li>
<li> <strong>Basic Bring up</strong>
+
<ul>
<li><a href="build_new_device.html">Building New Device</a></li>
<li><a href="bring_up.html">Bring up</a></li>
@@ -111,26 +128,39 @@
<li><a href="display_drivers.html">Display Drivers</a></li>
</ul>
</li>
+
<li> <strong>Multimedia</strong>
<ul>
- <li><a href="audio_sub_system.html">Audio Subsystem</a></li>
+ <li><a href="audio_sub_system.html">Audio</a></li>
+ <li><a href="camera.html">Camera</a></li>
</ul>
</li>
<li> <strong>Power Management</strong>
+
<ul>
<li><a href="power_management.html">Power Management</a></li>
</ul>
</li>
+
+ <li> <strong>Networking</strong>
+ <ul>
+ <li><a href="wifi.html">Wi-Fi</a></li>
+ <li><a href="gps.html">GPS</a></li>
+ <li><a href="bluetooth.html">Bluetooth</a></li>
+ </ul>
+ </li>
+
<li> <strong>Telephony</strong>
<ul>
<li><a href="telephony.html">Radio Interface Layer</a></li>
+
</ul>
</li>
<li> <strong>Testing</strong>
<ul>
- <li><a href="instrumentation_framework.html">Instrumentation Framework</a></li>
<li><a href="instrumentation_testing.html">Instrumentation Testing</a></li>
</ul>
+
</li>
</ul>
</li>
@@ -297,7 +327,7 @@
pageTracker._trackPageview();
} catch(e) {}
</script>
-<div id="jd-build-id"> v0.3 - 9 June 2008</div>
+<div id="jd-build-id"> v0.6 - 25 November 2008</div>
</div></div></div></body>
</html>
diff --git a/pdk/docs/build_system.html b/pdk/docs/build_system.html
index 32e1c3e..4286e71 100755
--- a/pdk/docs/build_system.html
+++ b/pdk/docs/build_system.html
@@ -2,11 +2,23 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
-<title>Android - Build System</title>
+<title>Android - Porting Guide</title>
<script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=internal-codesite" type="text/javascript"></script>
<script src="http://code.google.com/js/jquery.js" type="text/javascript"></script>
<script type="text/javascript">var _tocPath_ = 'http://code.google.com/android/_toc.ezt';</script>
<script src="http://code.google.com/js/codesite.pack.01312008.js" type="text/javascript"></script>
+<script language="JavaScript">
+function resizeHeight() {
+ if(document.getElementById && !(document.all)) {
+ height= document.getElementById('doxygen').contentDocument.body.scrollHeight + 20;
+ document.getElementById('doxygen').style.height = height;
+ }
+ else if(document.all) {
+ height= document.frames('doxygen').document.body.scrollHeight + 20;
+ document.all.doxygen.style.height = height;
+ }
+}
+</script>
<link href="http://code.google.com/css/codesite.pack.01312008.css" type="text/css" rel="stylesheet">
</link>
@@ -33,6 +45,7 @@
<div id="skipto"> </div>
<div id="langpref">
<!--<a class="dropdown" href="/">English</a> <span>|</span> <a href="/more/">Site Directory</a> -->
+
</div>
<div id="gc-header">
<div id="logo"><a href="http://code.google.com/android/index.html"><img src="http://code.google.com/android/images/logo_android.gif" alt="Android"/></a></div>
@@ -51,6 +64,7 @@
}
</style>
</noscript>
+
<div id="searchForm2" class="searchForm2" style="display:none">
<form id="searchbox_001456098540849067467:6whlsytkdqg" action="http://www.google.com/cse">
<input type="hidden" name="cx" value="001456098540849067467:6whlsytkdqg" />
@@ -59,6 +73,7 @@
<input type="submit" name="sa" value="Search" title="Search"/>
<br/>
<div class="greytext">e.g. "ajax apis" or "open source"</div>
+
</form>
</div>
<!-- end searchForm2 -->
@@ -71,15 +86,18 @@
<div id="codesiteContent">
<a name="gc-topnav-anchor"></a>
<div id="gc-topnav">
+
<h1>Android Platform Development Kit</h1>
<ul class="gc-topnav-tabs">
<li id="sdk_link"> <a href="http://code.google.com/android/index.html" title="Android Software Development Kit">SDK</a> </li>
<li id="docs_link"> <a href="index.html" title="Official Android documentation">Docs</a> </li>
<li id="faq_link"> <a href="http://code.google.com/android/kb/index.html" title="Answers to frequently asked questions about Android">FAQ</a> </li>
+
<li> <a href="http://android-developers.blogspot.com/" title="Official Android blog">Blog</a> </li>
<li> <a href="http://code.google.com/android/groups.html" title="Android developer forum">Group</a> </li>
<li> <a href="http://code.google.com/android/terms.html" title="Android terms of service">Terms</a> </li>
- <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20build_system.html%20v0.3%20-%209%20June%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+ <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20build_system.html%20v0.6%20-%2025%20November%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+
</ul>
</div>
<!-- end gc-topnav -->
@@ -91,19 +109,18 @@
<h1><a href="index.html">Documentation</a></h1>
<ul>
<li> <strong>Introduction</strong>
+
<ul>
<li><a href="system_requirements.html">Device Requirements</a></li>
</ul>
</li>
<li> <strong>Dev Environment Setup</strong>
<ul>
- <li><a href="source_setup_guide.html">Host System Setup</a></li>
- <li><a href="getting_source_code.html">Getting Source Code</a></li>
- <li> <a href="intro_source_code.html">Source Code Overview</a></li>
<li><a href="build_system.html">Build System</a></li>
</ul>
</li>
<li> <strong>Basic Bring up</strong>
+
<ul>
<li><a href="build_new_device.html">Building New Device</a></li>
<li><a href="bring_up.html">Bring up</a></li>
@@ -111,26 +128,39 @@
<li><a href="display_drivers.html">Display Drivers</a></li>
</ul>
</li>
+
<li> <strong>Multimedia</strong>
<ul>
- <li><a href="audio_sub_system.html">Audio Subsystem</a></li>
+ <li><a href="audio_sub_system.html">Audio</a></li>
+ <li><a href="camera.html">Camera</a></li>
</ul>
</li>
<li> <strong>Power Management</strong>
+
<ul>
<li><a href="power_management.html">Power Management</a></li>
</ul>
</li>
+
+ <li> <strong>Networking</strong>
+ <ul>
+ <li><a href="wifi.html">Wi-Fi</a></li>
+ <li><a href="gps.html">GPS</a></li>
+ <li><a href="bluetooth.html">Bluetooth</a></li>
+ </ul>
+ </li>
+
<li> <strong>Telephony</strong>
<ul>
<li><a href="telephony.html">Radio Interface Layer</a></li>
+
</ul>
</li>
<li> <strong>Testing</strong>
<ul>
- <li><a href="instrumentation_framework.html">Instrumentation Framework</a></li>
<li><a href="instrumentation_testing.html">Instrumentation Testing</a></li>
</ul>
+
</li>
</ul>
</li>
@@ -422,7 +452,7 @@
pageTracker._trackPageview();
} catch(e) {}
</script>
-<div id="jd-build-id"> v0.3 - 9 June 2008</div>
+<div id="jd-build-id"> v0.6 - 25 November 2008</div>
</div></div></div></body>
</html>
diff --git a/pdk/docs/camera.html b/pdk/docs/camera.html
new file mode 100755
index 0000000..ae44b68
--- /dev/null
+++ b/pdk/docs/camera.html
@@ -0,0 +1,280 @@
+
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
+<title>Android - Porting Guide</title>
+<script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=internal-codesite" type="text/javascript"></script>
+<script src="http://code.google.com/js/jquery.js" type="text/javascript"></script>
+<script type="text/javascript">var _tocPath_ = 'http://code.google.com/android/_toc.ezt';</script>
+<script src="http://code.google.com/js/codesite.pack.01312008.js" type="text/javascript"></script>
+<script language="JavaScript">
+function resizeHeight() {
+ if(document.getElementById && !(document.all)) {
+ height= document.getElementById('doxygen').contentDocument.body.scrollHeight + 20;
+ document.getElementById('doxygen').style.height = height;
+ }
+ else if(document.all) {
+ height= document.frames('doxygen').document.body.scrollHeight + 20;
+ document.all.doxygen.style.height = height;
+ }
+}
+</script>
+<link href="http://code.google.com/css/codesite.pack.01312008.css" type="text/css" rel="stylesheet">
+</link>
+
+<!--[if IE]><link rel="stylesheet" type="text/css" href="/css/iehacks.css" /><![endif]-->
+<script src="http://code.google.com/android/assets/search_autocomplete.js"></script>
+<link rel="stylesheet" type="text/css" href="http://code.google.com/css/semantic_headers.css" />
+<link rel="stylesheet" type="text/css" href="http://code.google.com/android/assets/style.css" />
+<script>
+ jQuery(document).ready(function() {
+ jQuery("pre").addClass("prettyprint");
+ });
+ </script>
+<style type="text/css">
+<!--
+h1,h2,h3 {
+ color: #000000;
+}
+-->
+</style>
+</head>
+<body class="gc-documentation">
+<div id="gc-container">
+<a name="top"></a>
+<div id="skipto"> </div>
+<div id="langpref">
+ <!--<a class="dropdown" href="/">English</a> <span>|</span> <a href="/more/">Site Directory</a> -->
+
+</div>
+<div id="gc-header">
+ <div id="logo"><a href="http://code.google.com/android/index.html"><img src="http://code.google.com/android/images/logo_android.gif" alt="Android"/></a></div>
+ <div id="search" style="inline">
+ <div id="searchForm" class="searchForm" style="height: 44px;">
+ <!--previously form was here-->
+ </div>
+ <!-- end searchForm -->
+ <noscript>
+ <style type="text/css">
+ .searchForm {
+ display : none !important;
+ }
+ .searchForm2 {
+ display : inline !important;
+ }
+ </style>
+ </noscript>
+
+ <div id="searchForm2" class="searchForm2" style="display:none">
+ <form id="searchbox_001456098540849067467:6whlsytkdqg" action="http://www.google.com/cse">
+ <input type="hidden" name="cx" value="001456098540849067467:6whlsytkdqg" />
+ <input type="hidden" name="cof" value="FORID:0" />
+ <input type="text" name="q" maxlength="2048" size="41" autocomplete="off" title="Google Code Search"/>
+ <input type="submit" name="sa" value="Search" title="Search"/>
+ <br/>
+ <div class="greytext">e.g. "ajax apis" or "open source"</div>
+
+ </form>
+ </div>
+ <!-- end searchForm2 -->
+ </div>
+ <!-- end search -->
+</div>
+<!-- end gc-header -->
+<div id="searchControl" class="search-control"></div>
+<!--[if IE]><iframe id="backiFrame" name="backiFrame" src='/dummy.html' style="display:none"></iframe><![endif]-->
+<div id="codesiteContent">
+<a name="gc-topnav-anchor"></a>
+<div id="gc-topnav">
+
+ <h1>Android Platform Development Kit</h1>
+ <ul class="gc-topnav-tabs">
+ <li id="sdk_link"> <a href="http://code.google.com/android/index.html" title="Android Software Development Kit">SDK</a> </li>
+ <li id="docs_link"> <a href="index.html" title="Official Android documentation">Docs</a> </li>
+ <li id="faq_link"> <a href="http://code.google.com/android/kb/index.html" title="Answers to frequently asked questions about Android">FAQ</a> </li>
+
+ <li> <a href="http://android-developers.blogspot.com/" title="Official Android blog">Blog</a> </li>
+ <li> <a href="http://code.google.com/android/groups.html" title="Android developer forum">Group</a> </li>
+ <li> <a href="http://code.google.com/android/terms.html" title="Android terms of service">Terms</a> </li>
+ <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20camera.html%20v0.6%20-%2025%20November%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+
+ </ul>
+</div>
+<!-- end gc-topnav -->
+<div class="g-section g-tpl-180">
+<a name="gc-toc"></a>
+<div class="g-unit g-first" id="gc-toc">
+ <ul>
+ <li>
+ <h1><a href="index.html">Documentation</a></h1>
+ <ul>
+ <li> <strong>Introduction</strong>
+
+ <ul>
+ <li><a href="system_requirements.html">Device Requirements</a></li>
+ </ul>
+ </li>
+ <li> <strong>Dev Environment Setup</strong>
+ <ul>
+ <li><a href="build_system.html">Build System</a></li>
+ </ul>
+ </li>
+ <li> <strong>Basic Bring up</strong>
+
+ <ul>
+ <li><a href="build_new_device.html">Building New Device</a></li>
+ <li><a href="bring_up.html">Bring up</a></li>
+ <li><a href="keymaps_keyboard_input.html">Keymaps and Keyboard</a></li>
+ <li><a href="display_drivers.html">Display Drivers</a></li>
+ </ul>
+ </li>
+
+ <li> <strong>Multimedia</strong>
+ <ul>
+ <li><a href="audio_sub_system.html">Audio</a></li>
+ <li><a href="camera.html">Camera</a></li>
+ </ul>
+ </li>
+ <li> <strong>Power Management</strong>
+
+ <ul>
+ <li><a href="power_management.html">Power Management</a></li>
+ </ul>
+ </li>
+
+ <li> <strong>Networking</strong>
+ <ul>
+ <li><a href="wifi.html">Wi-Fi</a></li>
+ <li><a href="gps.html">GPS</a></li>
+ <li><a href="bluetooth.html">Bluetooth</a></li>
+ </ul>
+ </li>
+
+ <li> <strong>Telephony</strong>
+ <ul>
+ <li><a href="telephony.html">Radio Interface Layer</a></li>
+
+ </ul>
+ </li>
+ <li> <strong>Testing</strong>
+ <ul>
+ <li><a href="instrumentation_testing.html">Instrumentation Testing</a></li>
+ </ul>
+
+ </li>
+ </ul>
+ </li>
+ </ul>
+</div>
+<a name="gc-pagecontent"></a>
+<div class="g-unit" id="gc-pagecontent">
+<div id="jd-content">
+<div class="jd-descr">
+
+
+<a name="androidCameraTitle"></a><h1>Camera Subsystem</h1>
+
+
+
+<a name="toc"/>
+<div style="padding:10px">
+<a href="#androidCameraIntroduction">Introduction</a><br/>
+<a href="#androidCameraBuildingDriver">Building a Camera Library</a><br/>
+<a href="#androidCameraSequenceDiagrams">Sequence Diagrams</a><br/><div style="padding-left:40px">
+
+<a href="#androidCameraSequenceDiagramsPreview">Preview</a><br/>
+<a href="#androidCameraSequenceDiagramsTakePic">Taking a Picture</a><br/></div>
+<a href="#androidCameraInterfaceIntro">Interface</a><br/></div></font></div>
+
+<a name="androidCameraIntroduction"></a><h2>Introduction</h2>
+
+<p>Android's camera subsystem connects the camera application to the application framework and user space libraries, which in turn communicate with the camera hardware layer that operates the physical camera.</p>
+<p>The diagram below illustrates the structure of the camera subsystem.</p>
+<p><img src="androidCameraArchitecture.gif"></p>
+
+
+<a name="androidCameraBuildingDriver"></a><h2>Building a Camera Library</h2>
+
+<p>To implement a camera driver, create a shared library that implements the interface defined in <code>CameraHardwareInterface.h</code>. You must name your shared library <code>libcamera.so</code> so that it will get loaded from <code>/system/lib</code> at runtime. Place libcamera sources and <code>Android.mk</code> in <code>partner/acme/chipset_or_board/libcamera/</code>.</p>
+<p>The following stub <code>Android.mk</code> file ensures that <code>libcamera</code> compiles and links to the appropriate libraries:</p>
+<pre class="prettify">
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libcamera
+
+LOCAL_SHARED_LIBRARIES := \
+ libutils \
+ librpc \
+ liblog
+
+LOCAL_SRC_FILES += MyCameraHardware.cpp
+
+LOCAL_CFLAGS +=
+
+LOCAL_C_INCLUDES +=
+
+LOCAL_STATIC_LIBRARIES += \
+ libcamera-common \
+ libclock-rpc \
+ libcommondefs-rpc
+
+include $(BUILD_SHARED_LIBRARY)
+</pre>
+
+
+<a name="androidCameraSequenceDiagrams"></a><h2>Sequence Diagrams</h2>
+
+
+
+<a name="androidCameraSequenceDiagramsPreview"></a><h3>Preview</h3>
+
+<p>The following diagram illustrates the sequence of function calls and actions necessary for your camera to preview.</p>
+<img src="cameraPreview.jpg">
+
+
+<a name="androidCameraSequenceDiagramsTakePic"></a><h3>Taking a Picture</h3>
+
+<p>The following diagram illustrates the sequence of function calls and actions necessary for your camera to take a picture.</p>
+<img src="cameraTakePicture.jpg">
+
+
+<a name="androidCameraInterfaceIntro"></a><h2>Interface</h2>
+
+
+
+<p class="note"><strong>Note</strong>: This document relies on some Doxygen-generated content that appears in an iFrame below. To return to the Doxygen default content for this page, <a href="camera.html">click here</a>.</p>
+
+
+<iframe onLoad="resizeHeight();" src="_camera_hardware_interface_8h.html" scrolling="no" scroll="no" id="doxygen" marginwidth="0" marginheight="0" frameborder="0" style="width:100%;"></iframe>
+
+
+<p><span class="lh2"><a name="androidFooter"></a></span>
+
+ </div>
+ </div>
+ <!-- end gc-pagecontent -->
+ </div>
+ <!-- end gooey wrapper -->
+ </div>
+ <!-- end codesearchresults -->
+ <div id="gc-footer" dir="ltr">
+ <div class="text"> ©2008 Google<!-- - <a href="/">Code Home</a> - <a href="http://www.google.com/accounts/TOS">Site Terms of Service</a> - <a href="http://www.google.com/privacy.html">Privacy Policy</a> - <a href="/more">Site Directory</a> --></div>
+ </div>
+ <!-- end gc-footer -->
+</div>
+<!-- end gc-containter -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-18071-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+<div id="jd-build-id"> v0.6 - 25 November 2008</div>
+</div></div></div></body>
+</html>
+
diff --git a/pdk/docs/cameraPreview.jpg b/pdk/docs/cameraPreview.jpg
new file mode 100755
index 0000000..3dea011
--- /dev/null
+++ b/pdk/docs/cameraPreview.jpg
Binary files differ
diff --git a/pdk/docs/cameraTakePicture.jpg b/pdk/docs/cameraTakePicture.jpg
new file mode 100755
index 0000000..4ac6d95
--- /dev/null
+++ b/pdk/docs/cameraTakePicture.jpg
Binary files differ
diff --git a/pdk/docs/classandroid_1_1_audio_hardware_interface.html b/pdk/docs/classandroid_1_1_audio_hardware_interface.html
new file mode 100755
index 0000000..d2e9ac8
--- /dev/null
+++ b/pdk/docs/classandroid_1_1_audio_hardware_interface.html
@@ -0,0 +1,584 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li class="current"><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="functions.html"><span>Data Fields</span></a></li>
+ </ul>
+ </div>
+ <div class="navpath"><a class="el" href="namespaceandroid.html">android</a>::<a class="el" href="classandroid_1_1_audio_hardware_interface.html">AudioHardwareInterface</a>
+ </div>
+</div>
+<div class="contents">
+<h1>android::AudioHardwareInterface Class Reference</h1><!-- doxytag: class="android::AudioHardwareInterface" --><a class="el" href="_audio_hardware_interface_8h.html">AudioHardwareInterface.h</a> defines the interface to the audio hardware abstraction layer.
+<a href="#_details">More...</a>
+<p>
+<code>#include <<a class="el" href="_audio_hardware_interface_8h-source.html">AudioHardwareInterface.h</a>></code>
+<p>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Public Member Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_hardware_interface.html#b7e19e09fa6cbc07c127122fa9866c50">initCheck</a> ()=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">check to see if the audio hardware interface has been initialized. <a href="#b7e19e09fa6cbc07c127122fa9866c50"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_hardware_interface.html#61121d365bb4d182bdec2c1b12fb1178">standby</a> ()=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">put the audio hardware into standby mode to conserve power. <a href="#61121d365bb4d182bdec2c1b12fb1178"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_hardware_interface.html#7b7418072df1eeaacc89cd0c725755f6">setVoiceVolume</a> (float volume)=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">set the audio volume of a voice call. <a href="#7b7418072df1eeaacc89cd0c725755f6"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_hardware_interface.html#925092e556eb89f304bcebb09f90c9a3">setMasterVolume</a> (float volume)=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">set the audio volume for all audio activities other than voice call. <a href="#925092e556eb89f304bcebb09f90c9a3"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_hardware_interface.html#39b2690e19219425b8cff093ef83bfb1">setRouting</a> (int mode, uint32_t routes)=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Audio routing methods. <a href="#39b2690e19219425b8cff093ef83bfb1"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_hardware_interface.html#1886de8fff2342ae628dbbbc0c45ba83">getRouting</a> (int mode, uint32_t *routes)=0</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_hardware_interface.html#aaf2a429c240f00b21836794849b430f">setMode</a> (int mode)=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">setMode is called when the audio mode changes. <a href="#aaf2a429c240f00b21836794849b430f"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_hardware_interface.html#8466c76328a51b8a83da103032abba55">getMode</a> (int *mode)=0</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_hardware_interface.html#be35b7cb738531939a3ac9abc5514621">setMicMute</a> (bool state)=0</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_hardware_interface.html#15d3c33d7e3f965dc2588c537f05a133">getMicMute</a> (bool *state)=0</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_hardware_interface.html#a1b477901df48b3a27103a77e6bb39c8">setParameter</a> (const char *key, const char *value)=0</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual size_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_hardware_interface.html#19f68d873b2a6e4c00c017c580170395">getInputBufferSize</a> (uint32_t sampleRate, int format, int channelCount)=0</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual <a class="el" href="classandroid_1_1_audio_stream_out.html">AudioStreamOut</a> * </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_hardware_interface.html#eda0986e145c8dd68d21cb79051f94f9">openOutputStream</a> (int format=0, int channelCount=0, uint32_t sampleRate=0, status_t *status=0)=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">This method creates and opens the audio hardware output stream. <a href="#eda0986e145c8dd68d21cb79051f94f9"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual <a class="el" href="classandroid_1_1_audio_stream_in.html">AudioStreamIn</a> * </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_hardware_interface.html#efb777d192fcbcd65458fa4f2d976476">openInputStream</a> (int format, int channelCount, uint32_t sampleRate, status_t *status)=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">This method creates and opens the audio hardware input stream. <a href="#efb777d192fcbcd65458fa4f2d976476"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_hardware_interface.html#05f035af60e67a22251175b44a089f69">dumpState</a> (int fd, const Vector< String16 > &args)=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">This method dumps the state of the audio hardware. <a href="#05f035af60e67a22251175b44a089f69"></a><br></td></tr>
+<tr><td colspan="2"><br><h2>Static Public Member Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">static <a class="el" href="classandroid_1_1_audio_hardware_interface.html">AudioHardwareInterface</a> * </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_hardware_interface.html#aa5ae45e9ad969fefc494e103cf5068d">create</a> ()</td></tr>
+
+<tr><td colspan="2"><br><h2>Protected Member Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_hardware_interface.html#d82c3e4827f275abf28eb872e8751e1f">doRouting</a> ()=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">doRouting actually initiates the routing. <a href="#d82c3e4827f275abf28eb872e8751e1f"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_hardware_interface.html#371f198a416cb726804e0f47e8763217">dump</a> (int fd, const Vector< String16 > &args)=0</td></tr>
+
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+<a class="el" href="_audio_hardware_interface_8h.html">AudioHardwareInterface.h</a> defines the interface to the audio hardware abstraction layer.
+<p>
+The interface supports setting and getting parameters, selecting audio routing paths, and defining input and output streams.<p>
+AudioFlinger initializes the audio hardware and immediately opens an output stream. You can set Audio routing to output to handset, speaker, Bluetooth, or a headset.<p>
+The audio input stream is initialized when AudioFlinger is called to carry out a record operation.
+<p>Definition at line <a class="el" href="_audio_hardware_interface_8h-source.html#l00144">144</a> of file <a class="el" href="_audio_hardware_interface_8h-source.html">AudioHardwareInterface.h</a>.</p>
+<hr><h2>Member Function Documentation</h2>
+<a class="anchor" name="b7e19e09fa6cbc07c127122fa9866c50"></a><!-- doxytag: member="android::AudioHardwareInterface::initCheck" ref="b7e19e09fa6cbc07c127122fa9866c50" args="()=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::AudioHardwareInterface::initCheck </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+check to see if the audio hardware interface has been initialized.
+<p>
+return status based on values defined in include/utils/Errors.h
+</div>
+</div><p>
+<a class="anchor" name="61121d365bb4d182bdec2c1b12fb1178"></a><!-- doxytag: member="android::AudioHardwareInterface::standby" ref="61121d365bb4d182bdec2c1b12fb1178" args="()=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::AudioHardwareInterface::standby </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+put the audio hardware into standby mode to conserve power.
+<p>
+Returns status based on include/utils/Errors.h
+</div>
+</div><p>
+<a class="anchor" name="7b7418072df1eeaacc89cd0c725755f6"></a><!-- doxytag: member="android::AudioHardwareInterface::setVoiceVolume" ref="7b7418072df1eeaacc89cd0c725755f6" args="(float volume)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::AudioHardwareInterface::setVoiceVolume </td>
+ <td>(</td>
+ <td class="paramtype">float </td>
+ <td class="paramname"> <em>volume</em> </td>
+ <td> ) </td>
+ <td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+set the audio volume of a voice call.
+<p>
+Range is between 0.0 and 1.0
+</div>
+</div><p>
+<a class="anchor" name="925092e556eb89f304bcebb09f90c9a3"></a><!-- doxytag: member="android::AudioHardwareInterface::setMasterVolume" ref="925092e556eb89f304bcebb09f90c9a3" args="(float volume)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::AudioHardwareInterface::setMasterVolume </td>
+ <td>(</td>
+ <td class="paramtype">float </td>
+ <td class="paramname"> <em>volume</em> </td>
+ <td> ) </td>
+ <td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+set the audio volume for all audio activities other than voice call.
+<p>
+Range between 0.0 and 1.0. If any value other than NO_ERROR is returned, the software mixer will emulate this capability.
+</div>
+</div><p>
+<a class="anchor" name="39b2690e19219425b8cff093ef83bfb1"></a><!-- doxytag: member="android::AudioHardwareInterface::setRouting" ref="39b2690e19219425b8cff093ef83bfb1" args="(int mode, uint32_t routes)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::AudioHardwareInterface::setRouting </td>
+ <td>(</td>
+ <td class="paramtype">int </td>
+ <td class="paramname"> <em>mode</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">uint32_t </td>
+ <td class="paramname"> <em>routes</em></td><td> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Audio routing methods.
+<p>
+Routes defined in include/hardware/AudioSystem.h. Audio routes can be (ROUTE_EARPIECE | ROUTE_SPEAKER | ROUTE_BLUETOOTH | ROUTE_HEADSET)<p>
+setRouting sets the routes for a mode. This is called at startup. It is also called when a new device is connected, such as a wired headset is plugged in or a Bluetooth headset is paired.
+</div>
+</div><p>
+<a class="anchor" name="1886de8fff2342ae628dbbbc0c45ba83"></a><!-- doxytag: member="android::AudioHardwareInterface::getRouting" ref="1886de8fff2342ae628dbbbc0c45ba83" args="(int mode, uint32_t *routes)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::AudioHardwareInterface::getRouting </td>
+ <td>(</td>
+ <td class="paramtype">int </td>
+ <td class="paramname"> <em>mode</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">uint32_t * </td>
+ <td class="paramname"> <em>routes</em></td><td> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="aaf2a429c240f00b21836794849b430f"></a><!-- doxytag: member="android::AudioHardwareInterface::setMode" ref="aaf2a429c240f00b21836794849b430f" args="(int mode)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::AudioHardwareInterface::setMode </td>
+ <td>(</td>
+ <td class="paramtype">int </td>
+ <td class="paramname"> <em>mode</em> </td>
+ <td> ) </td>
+ <td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+setMode is called when the audio mode changes.
+<p>
+NORMAL mode is for standard audio playback, RINGTONE when a ringtone is playing, and IN_CALL when a call is in progress.
+</div>
+</div><p>
+<a class="anchor" name="8466c76328a51b8a83da103032abba55"></a><!-- doxytag: member="android::AudioHardwareInterface::getMode" ref="8466c76328a51b8a83da103032abba55" args="(int *mode)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::AudioHardwareInterface::getMode </td>
+ <td>(</td>
+ <td class="paramtype">int * </td>
+ <td class="paramname"> <em>mode</em> </td>
+ <td> ) </td>
+ <td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="be35b7cb738531939a3ac9abc5514621"></a><!-- doxytag: member="android::AudioHardwareInterface::setMicMute" ref="be35b7cb738531939a3ac9abc5514621" args="(bool state)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::AudioHardwareInterface::setMicMute </td>
+ <td>(</td>
+ <td class="paramtype">bool </td>
+ <td class="paramname"> <em>state</em> </td>
+ <td> ) </td>
+ <td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="15d3c33d7e3f965dc2588c537f05a133"></a><!-- doxytag: member="android::AudioHardwareInterface::getMicMute" ref="15d3c33d7e3f965dc2588c537f05a133" args="(bool *state)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::AudioHardwareInterface::getMicMute </td>
+ <td>(</td>
+ <td class="paramtype">bool * </td>
+ <td class="paramname"> <em>state</em> </td>
+ <td> ) </td>
+ <td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="a1b477901df48b3a27103a77e6bb39c8"></a><!-- doxytag: member="android::AudioHardwareInterface::setParameter" ref="a1b477901df48b3a27103a77e6bb39c8" args="(const char *key, const char *value)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::AudioHardwareInterface::setParameter </td>
+ <td>(</td>
+ <td class="paramtype">const char * </td>
+ <td class="paramname"> <em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const char * </td>
+ <td class="paramname"> <em>value</em></td><td> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="19f68d873b2a6e4c00c017c580170395"></a><!-- doxytag: member="android::AudioHardwareInterface::getInputBufferSize" ref="19f68d873b2a6e4c00c017c580170395" args="(uint32_t sampleRate, int format, int channelCount)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual size_t android::AudioHardwareInterface::getInputBufferSize </td>
+ <td>(</td>
+ <td class="paramtype">uint32_t </td>
+ <td class="paramname"> <em>sampleRate</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int </td>
+ <td class="paramname"> <em>format</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int </td>
+ <td class="paramname"> <em>channelCount</em></td><td> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="eda0986e145c8dd68d21cb79051f94f9"></a><!-- doxytag: member="android::AudioHardwareInterface::openOutputStream" ref="eda0986e145c8dd68d21cb79051f94f9" args="(int format=0, int channelCount=0, uint32_t sampleRate=0, status_t *status=0)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual <a class="el" href="classandroid_1_1_audio_stream_out.html">AudioStreamOut</a>* android::AudioHardwareInterface::openOutputStream </td>
+ <td>(</td>
+ <td class="paramtype">int </td>
+ <td class="paramname"> <em>format</em> = <code>0</code>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int </td>
+ <td class="paramname"> <em>channelCount</em> = <code>0</code>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">uint32_t </td>
+ <td class="paramname"> <em>sampleRate</em> = <code>0</code>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">status_t * </td>
+ <td class="paramname"> <em>status</em> = <code>0</code></td><td> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+This method creates and opens the audio hardware output stream.
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="efb777d192fcbcd65458fa4f2d976476"></a><!-- doxytag: member="android::AudioHardwareInterface::openInputStream" ref="efb777d192fcbcd65458fa4f2d976476" args="(int format, int channelCount, uint32_t sampleRate, status_t *status)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual <a class="el" href="classandroid_1_1_audio_stream_in.html">AudioStreamIn</a>* android::AudioHardwareInterface::openInputStream </td>
+ <td>(</td>
+ <td class="paramtype">int </td>
+ <td class="paramname"> <em>format</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int </td>
+ <td class="paramname"> <em>channelCount</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">uint32_t </td>
+ <td class="paramname"> <em>sampleRate</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">status_t * </td>
+ <td class="paramname"> <em>status</em></td><td> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+This method creates and opens the audio hardware input stream.
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="05f035af60e67a22251175b44a089f69"></a><!-- doxytag: member="android::AudioHardwareInterface::dumpState" ref="05f035af60e67a22251175b44a089f69" args="(int fd, const Vector< String16 > &args)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::AudioHardwareInterface::dumpState </td>
+ <td>(</td>
+ <td class="paramtype">int </td>
+ <td class="paramname"> <em>fd</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const Vector< String16 > & </td>
+ <td class="paramname"> <em>args</em></td><td> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+This method dumps the state of the audio hardware.
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="aa5ae45e9ad969fefc494e103cf5068d"></a><!-- doxytag: member="android::AudioHardwareInterface::create" ref="aa5ae45e9ad969fefc494e103cf5068d" args="()" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">static <a class="el" href="classandroid_1_1_audio_hardware_interface.html">AudioHardwareInterface</a>* android::AudioHardwareInterface::create </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td><code> [static]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="d82c3e4827f275abf28eb872e8751e1f"></a><!-- doxytag: member="android::AudioHardwareInterface::doRouting" ref="d82c3e4827f275abf28eb872e8751e1f" args="()=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::AudioHardwareInterface::doRouting </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td><code> [protected, pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+doRouting actually initiates the routing.
+<p>
+A call to setRouting or setMode may result in a routing change. The generic logic calls doRouting when required. If the device has any special requirements these methods can be overriden.
+</div>
+</div><p>
+<a class="anchor" name="371f198a416cb726804e0f47e8763217"></a><!-- doxytag: member="android::AudioHardwareInterface::dump" ref="371f198a416cb726804e0f47e8763217" args="(int fd, const Vector< String16 > &args)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::AudioHardwareInterface::dump </td>
+ <td>(</td>
+ <td class="paramtype">int </td>
+ <td class="paramname"> <em>fd</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const Vector< String16 > & </td>
+ <td class="paramname"> <em>args</em></td><td> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td><code> [protected, pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+
+</div>
+</div><p>
+<hr>The documentation for this class was generated from the following file:<ul>
+<li><a class="el" href="_audio_hardware_interface_8h-source.html">AudioHardwareInterface.h</a></ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/classandroid_1_1_audio_stream_in.html b/pdk/docs/classandroid_1_1_audio_stream_in.html
new file mode 100755
index 0000000..5439194
--- /dev/null
+++ b/pdk/docs/classandroid_1_1_audio_stream_in.html
@@ -0,0 +1,292 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li class="current"><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="functions.html"><span>Data Fields</span></a></li>
+ </ul>
+ </div>
+ <div class="navpath"><a class="el" href="namespaceandroid.html">android</a>::<a class="el" href="classandroid_1_1_audio_stream_in.html">AudioStreamIn</a>
+ </div>
+</div>
+<div class="contents">
+<h1>android::AudioStreamIn Class Reference</h1><!-- doxytag: class="android::AudioStreamIn" --><a class="el" href="classandroid_1_1_audio_stream_in.html" title="AudioStreamIn is the abstraction interface for the audio input hardware.">AudioStreamIn</a> is the abstraction interface for the audio input hardware.
+<a href="#_details">More...</a>
+<p>
+<code>#include <<a class="el" href="_audio_hardware_interface_8h-source.html">AudioHardwareInterface.h</a>></code>
+<p>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Public Member Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_in.html#72067577568bbdd0163c1369fe80f101">~AudioStreamIn</a> ()=0</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual size_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_in.html#a458f9cde3edde82f256af7eaa7b2ddf">bufferSize</a> () const =0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">return the input buffer size allowed by audio driver <a href="#a458f9cde3edde82f256af7eaa7b2ddf"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual int </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_in.html#04f84006dd5f2e0a5e512897a039f851">channelCount</a> () const =0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">return the number of audio input channels <a href="#04f84006dd5f2e0a5e512897a039f851"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual int </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_in.html#4ade98c5243b9ed5f3a71a8f36e74b36">format</a> () const =0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">return audio format in 8bit or 16bit PCM format - eg. <a href="#4ade98c5243b9ed5f3a71a8f36e74b36"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_in.html#43d2c6b97806c005f0717a7bb6f7595c">frameSize</a> () const </td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">return the frame size (number of bytes per sample). <a href="#43d2c6b97806c005f0717a7bb6f7595c"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_in.html#339822afb3f2f2ac1b4c775d31d12440">setGain</a> (float gain)=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">set the input gain for the audio driver. <a href="#339822afb3f2f2ac1b4c775d31d12440"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual ssize_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_in.html#7c313cbfbb47dafd90f3225bcd26e592">read</a> (void *buffer, ssize_t bytes)=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">read audio buffer in from audio driver <a href="#7c313cbfbb47dafd90f3225bcd26e592"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_in.html#18c3760208bfb99498715a0d4977f675">dump</a> (int fd, const Vector< String16 > &args)=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">dump the state of the audio input device <a href="#18c3760208bfb99498715a0d4977f675"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_in.html#93fab46e8afdbaedd4d20cc6ee2b7c41">standby</a> ()=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Put the audio hardware input into standby mode. <a href="#93fab46e8afdbaedd4d20cc6ee2b7c41"></a><br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+<a class="el" href="classandroid_1_1_audio_stream_in.html" title="AudioStreamIn is the abstraction interface for the audio input hardware.">AudioStreamIn</a> is the abstraction interface for the audio input hardware.
+<p>
+It defines the various properties of the audio hardware input driver.
+<p>Definition at line <a class="el" href="_audio_hardware_interface_8h-source.html#l00093">93</a> of file <a class="el" href="_audio_hardware_interface_8h-source.html">AudioHardwareInterface.h</a>.</p>
+<hr><h2>Constructor & Destructor Documentation</h2>
+<a class="anchor" name="72067577568bbdd0163c1369fe80f101"></a><!-- doxytag: member="android::AudioStreamIn::~AudioStreamIn" ref="72067577568bbdd0163c1369fe80f101" args="()=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual android::AudioStreamIn::~AudioStreamIn </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+
+</div>
+</div><p>
+<hr><h2>Member Function Documentation</h2>
+<a class="anchor" name="a458f9cde3edde82f256af7eaa7b2ddf"></a><!-- doxytag: member="android::AudioStreamIn::bufferSize" ref="a458f9cde3edde82f256af7eaa7b2ddf" args="() const =0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual size_t android::AudioStreamIn::bufferSize </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td> const<code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+return the input buffer size allowed by audio driver
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="04f84006dd5f2e0a5e512897a039f851"></a><!-- doxytag: member="android::AudioStreamIn::channelCount" ref="04f84006dd5f2e0a5e512897a039f851" args="() const =0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual int android::AudioStreamIn::channelCount </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td> const<code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+return the number of audio input channels
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="4ade98c5243b9ed5f3a71a8f36e74b36"></a><!-- doxytag: member="android::AudioStreamIn::format" ref="4ade98c5243b9ed5f3a71a8f36e74b36" args="() const =0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual int android::AudioStreamIn::format </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td> const<code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+return audio format in 8bit or 16bit PCM format - eg.
+<p>
+AudioSystem:PCM_16_BIT
+</div>
+</div><p>
+<a class="anchor" name="43d2c6b97806c005f0717a7bb6f7595c"></a><!-- doxytag: member="android::AudioStreamIn::frameSize" ref="43d2c6b97806c005f0717a7bb6f7595c" args="() const " -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">uint32_t android::AudioStreamIn::frameSize </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td> const<code> [inline]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+return the frame size (number of bytes per sample).
+<p>
+
+<p>Definition at line <a class="el" href="_audio_hardware_interface_8h-source.html#l00112">112</a> of file <a class="el" href="_audio_hardware_interface_8h-source.html">AudioHardwareInterface.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="339822afb3f2f2ac1b4c775d31d12440"></a><!-- doxytag: member="android::AudioStreamIn::setGain" ref="339822afb3f2f2ac1b4c775d31d12440" args="(float gain)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::AudioStreamIn::setGain </td>
+ <td>(</td>
+ <td class="paramtype">float </td>
+ <td class="paramname"> <em>gain</em> </td>
+ <td> ) </td>
+ <td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+set the input gain for the audio driver.
+<p>
+This method is for for future use
+</div>
+</div><p>
+<a class="anchor" name="7c313cbfbb47dafd90f3225bcd26e592"></a><!-- doxytag: member="android::AudioStreamIn::read" ref="7c313cbfbb47dafd90f3225bcd26e592" args="(void *buffer, ssize_t bytes)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual ssize_t android::AudioStreamIn::read </td>
+ <td>(</td>
+ <td class="paramtype">void * </td>
+ <td class="paramname"> <em>buffer</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">ssize_t </td>
+ <td class="paramname"> <em>bytes</em></td><td> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+read audio buffer in from audio driver
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="18c3760208bfb99498715a0d4977f675"></a><!-- doxytag: member="android::AudioStreamIn::dump" ref="18c3760208bfb99498715a0d4977f675" args="(int fd, const Vector< String16 > &args)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::AudioStreamIn::dump </td>
+ <td>(</td>
+ <td class="paramtype">int </td>
+ <td class="paramname"> <em>fd</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const Vector< String16 > & </td>
+ <td class="paramname"> <em>args</em></td><td> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+dump the state of the audio input device
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="93fab46e8afdbaedd4d20cc6ee2b7c41"></a><!-- doxytag: member="android::AudioStreamIn::standby" ref="93fab46e8afdbaedd4d20cc6ee2b7c41" args="()=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::AudioStreamIn::standby </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Put the audio hardware input into standby mode.
+<p>
+Returns status based on include/utils/Errors.h
+</div>
+</div><p>
+<hr>The documentation for this class was generated from the following file:<ul>
+<li><a class="el" href="_audio_hardware_interface_8h-source.html">AudioHardwareInterface.h</a></ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/classandroid_1_1_audio_stream_out.html b/pdk/docs/classandroid_1_1_audio_stream_out.html
new file mode 100755
index 0000000..5d727ee
--- /dev/null
+++ b/pdk/docs/classandroid_1_1_audio_stream_out.html
@@ -0,0 +1,316 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li class="current"><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="functions.html"><span>Data Fields</span></a></li>
+ </ul>
+ </div>
+ <div class="navpath"><a class="el" href="namespaceandroid.html">android</a>::<a class="el" href="classandroid_1_1_audio_stream_out.html">AudioStreamOut</a>
+ </div>
+</div>
+<div class="contents">
+<h1>android::AudioStreamOut Class Reference</h1><!-- doxytag: class="android::AudioStreamOut" --><a class="el" href="classandroid_1_1_audio_stream_out.html" title="AudioStreamOut is the abstraction interface for the audio output hardware.">AudioStreamOut</a> is the abstraction interface for the audio output hardware.
+<a href="#_details">More...</a>
+<p>
+<code>#include <<a class="el" href="_audio_hardware_interface_8h-source.html">AudioHardwareInterface.h</a>></code>
+<p>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Public Member Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_out.html#09074dbae95b82d4f83c513035a0034f">~AudioStreamOut</a> ()=0</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_out.html#6bb028e125d13289f26d3d74f851c921">sampleRate</a> () const =0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">return audio sampling rate in hz - eg. <a href="#6bb028e125d13289f26d3d74f851c921"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual size_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_out.html#7b3c5f2ce79b9b6f167408f63d19af0a">bufferSize</a> () const =0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">returns size of output buffer - eg. <a href="#7b3c5f2ce79b9b6f167408f63d19af0a"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual int </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_out.html#4e880a5379c168e8f68c26827e41275b">channelCount</a> () const =0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">return number of output audio channels. <a href="#4e880a5379c168e8f68c26827e41275b"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual int </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_out.html#eb2b430bbff4eebd8fb8590507b1dce1">format</a> () const =0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">return audio format in 8bit or 16bit PCM format - eg. <a href="#eb2b430bbff4eebd8fb8590507b1dce1"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_out.html#66b7c4bb510db4060adfd03a376897d8">frameSize</a> () const </td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">return the frame size (number of bytes per sample). <a href="#66b7c4bb510db4060adfd03a376897d8"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_out.html#c698a3d95cf0829dcfe283cd5ea437cb">latency</a> () const =0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">return the audio hardware driver latency in milli seconds. <a href="#c698a3d95cf0829dcfe283cd5ea437cb"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_out.html#e6d301925d193c25561b42239c7f44b6">setVolume</a> (float volume)=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Use this method in situations where audio mixing is done in the hardware. <a href="#e6d301925d193c25561b42239c7f44b6"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual ssize_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_out.html#cba177e4a4a35a87ab9f8aa2a9c0e78e">write</a> (const void *buffer, size_t bytes)=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">write audio buffer to driver. <a href="#cba177e4a4a35a87ab9f8aa2a9c0e78e"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_out.html#97e3cc4610ba40d6c37b3d376a032b98">dump</a> (int fd, const Vector< String16 > &args)=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">dump the state of the audio output device <a href="#97e3cc4610ba40d6c37b3d376a032b98"></a><br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+<a class="el" href="classandroid_1_1_audio_stream_out.html" title="AudioStreamOut is the abstraction interface for the audio output hardware.">AudioStreamOut</a> is the abstraction interface for the audio output hardware.
+<p>
+It provides information about various properties of the audio output hardware driver.
+<p>Definition at line <a class="el" href="_audio_hardware_interface_8h-source.html#l00040">40</a> of file <a class="el" href="_audio_hardware_interface_8h-source.html">AudioHardwareInterface.h</a>.</p>
+<hr><h2>Constructor & Destructor Documentation</h2>
+<a class="anchor" name="09074dbae95b82d4f83c513035a0034f"></a><!-- doxytag: member="android::AudioStreamOut::~AudioStreamOut" ref="09074dbae95b82d4f83c513035a0034f" args="()=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual android::AudioStreamOut::~AudioStreamOut </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+
+</div>
+</div><p>
+<hr><h2>Member Function Documentation</h2>
+<a class="anchor" name="6bb028e125d13289f26d3d74f851c921"></a><!-- doxytag: member="android::AudioStreamOut::sampleRate" ref="6bb028e125d13289f26d3d74f851c921" args="() const =0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual uint32_t android::AudioStreamOut::sampleRate </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td> const<code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+return audio sampling rate in hz - eg.
+<p>
+44100
+</div>
+</div><p>
+<a class="anchor" name="7b3c5f2ce79b9b6f167408f63d19af0a"></a><!-- doxytag: member="android::AudioStreamOut::bufferSize" ref="7b3c5f2ce79b9b6f167408f63d19af0a" args="() const =0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual size_t android::AudioStreamOut::bufferSize </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td> const<code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+returns size of output buffer - eg.
+<p>
+4800
+</div>
+</div><p>
+<a class="anchor" name="4e880a5379c168e8f68c26827e41275b"></a><!-- doxytag: member="android::AudioStreamOut::channelCount" ref="4e880a5379c168e8f68c26827e41275b" args="() const =0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual int android::AudioStreamOut::channelCount </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td> const<code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+return number of output audio channels.
+<p>
+Acceptable values are 1 (mono) or 2 (stereo)
+</div>
+</div><p>
+<a class="anchor" name="eb2b430bbff4eebd8fb8590507b1dce1"></a><!-- doxytag: member="android::AudioStreamOut::format" ref="eb2b430bbff4eebd8fb8590507b1dce1" args="() const =0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual int android::AudioStreamOut::format </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td> const<code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+return audio format in 8bit or 16bit PCM format - eg.
+<p>
+AudioSystem:PCM_16_BIT
+</div>
+</div><p>
+<a class="anchor" name="66b7c4bb510db4060adfd03a376897d8"></a><!-- doxytag: member="android::AudioStreamOut::frameSize" ref="66b7c4bb510db4060adfd03a376897d8" args="() const " -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">uint32_t android::AudioStreamOut::frameSize </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td> const<code> [inline]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+return the frame size (number of bytes per sample).
+<p>
+
+<p>Definition at line <a class="el" href="_audio_hardware_interface_8h-source.html#l00065">65</a> of file <a class="el" href="_audio_hardware_interface_8h-source.html">AudioHardwareInterface.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="c698a3d95cf0829dcfe283cd5ea437cb"></a><!-- doxytag: member="android::AudioStreamOut::latency" ref="c698a3d95cf0829dcfe283cd5ea437cb" args="() const =0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual uint32_t android::AudioStreamOut::latency </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td> const<code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+return the audio hardware driver latency in milli seconds.
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="e6d301925d193c25561b42239c7f44b6"></a><!-- doxytag: member="android::AudioStreamOut::setVolume" ref="e6d301925d193c25561b42239c7f44b6" args="(float volume)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::AudioStreamOut::setVolume </td>
+ <td>(</td>
+ <td class="paramtype">float </td>
+ <td class="paramname"> <em>volume</em> </td>
+ <td> ) </td>
+ <td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Use this method in situations where audio mixing is done in the hardware.
+<p>
+This method serves as a direct interface with hardware, allowing you to directly set the volume as apposed to via the framework. This method might produce multiple PCM outputs or hardware accelerated codecs, such as MP3 or AAC.
+</div>
+</div><p>
+<a class="anchor" name="cba177e4a4a35a87ab9f8aa2a9c0e78e"></a><!-- doxytag: member="android::AudioStreamOut::write" ref="cba177e4a4a35a87ab9f8aa2a9c0e78e" args="(const void *buffer, size_t bytes)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual ssize_t android::AudioStreamOut::write </td>
+ <td>(</td>
+ <td class="paramtype">const void * </td>
+ <td class="paramname"> <em>buffer</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"> <em>bytes</em></td><td> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+write audio buffer to driver.
+<p>
+Returns number of bytes written
+</div>
+</div><p>
+<a class="anchor" name="97e3cc4610ba40d6c37b3d376a032b98"></a><!-- doxytag: member="android::AudioStreamOut::dump" ref="97e3cc4610ba40d6c37b3d376a032b98" args="(int fd, const Vector< String16 > &args)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::AudioStreamOut::dump </td>
+ <td>(</td>
+ <td class="paramtype">int </td>
+ <td class="paramname"> <em>fd</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const Vector< String16 > & </td>
+ <td class="paramname"> <em>args</em></td><td> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+dump the state of the audio output device
+<p>
+
+</div>
+</div><p>
+<hr>The documentation for this class was generated from the following file:<ul>
+<li><a class="el" href="_audio_hardware_interface_8h-source.html">AudioHardwareInterface.h</a></ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/classandroid_1_1_camera_hardware_interface.html b/pdk/docs/classandroid_1_1_camera_hardware_interface.html
new file mode 100755
index 0000000..cddb82c
--- /dev/null
+++ b/pdk/docs/classandroid_1_1_camera_hardware_interface.html
@@ -0,0 +1,393 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li class="current"><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="functions.html"><span>Data Fields</span></a></li>
+ </ul>
+ </div>
+ <div class="navpath"><a class="el" href="namespaceandroid.html">android</a>::<a class="el" href="classandroid_1_1_camera_hardware_interface.html">CameraHardwareInterface</a>
+ </div>
+</div>
+<div class="contents">
+<h1>android::CameraHardwareInterface Class Reference</h1><!-- doxytag: class="android::CameraHardwareInterface" --><a class="el" href="_camera_hardware_interface_8h.html">CameraHardwareInterface.h</a> defines the interface to the camera hardware abstraction layer, used for setting and getting parameters, live previewing, and taking pictures.
+<a href="#_details">More...</a>
+<p>
+<code>#include <<a class="el" href="_camera_hardware_interface_8h-source.html">CameraHardwareInterface.h</a>></code>
+<p>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Public Member Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_camera_hardware_interface.html#99f4ab74b58cd4b23e0fb00a46a60cb1">~CameraHardwareInterface</a> ()</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual sp< IMemoryHeap > </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_camera_hardware_interface.html#9d4071fb234a0c2e7bf6ea78e723f2f4">getPreviewHeap</a> () const =0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Return the IMemoryHeap for the preview image heap. <a href="#9d4071fb234a0c2e7bf6ea78e723f2f4"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_camera_hardware_interface.html#62def8031dee8bdab7933770708a6312">startPreview</a> (<a class="el" href="namespaceandroid.html#d32b08663d42356404e2eb971e271636">preview_callback</a> cb, void *user)=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Start preview mode. <a href="#62def8031dee8bdab7933770708a6312"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual void </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_camera_hardware_interface.html#34faa77065f415b93cb1acf84fc788bf">stopPreview</a> ()=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Stop a previously started preview. <a href="#34faa77065f415b93cb1acf84fc788bf"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_camera_hardware_interface.html#0dda73938e9b18326dd48bd721dbd515">autoFocus</a> (<a class="el" href="namespaceandroid.html#4dca8d8b824ca9a684358133da0ec8f2">autofocus_callback</a>, void *user)=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Start auto focus, the callback routine is called once when focusing is complete. <a href="#0dda73938e9b18326dd48bd721dbd515"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_camera_hardware_interface.html#2aedf65cad695ce439029f37a7cb66c4">takePicture</a> (<a class="el" href="namespaceandroid.html#04c83209c2627e2d303320712ca9ee65">shutter_callback</a>, <a class="el" href="namespaceandroid.html#a97926709e452d66360cb9b24736969e">raw_callback</a>, <a class="el" href="namespaceandroid.html#c21980d4be1e0cc458399ecf5374d473">jpeg_callback</a>, void *user)=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Take a picture. <a href="#2aedf65cad695ce439029f37a7cb66c4"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_camera_hardware_interface.html#da8faf376215a605357d26afa1b79386">cancelPicture</a> (bool cancel_shutter, bool cancel_raw, bool cancel_jpeg)=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Cancel a picture that was started with takePicture. <a href="#da8faf376215a605357d26afa1b79386"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_camera_hardware_interface.html#82e54ede14bd263274bbc8777bafc384">setParameters</a> (const CameraParameters &params)=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Set the camera parameters. <a href="#82e54ede14bd263274bbc8777bafc384"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual CameraParameters </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_camera_hardware_interface.html#4c748a3c0aa3c5f2333e0abcdbeb15cb">getParameters</a> () const =0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Return the camera parameters. <a href="#4c748a3c0aa3c5f2333e0abcdbeb15cb"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual void </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_camera_hardware_interface.html#df65310b8aa176e0ce5f08b87d6b7eb8">release</a> ()=0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Release the hardware resources owned by this object. <a href="#df65310b8aa176e0ce5f08b87d6b7eb8"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">virtual status_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_camera_hardware_interface.html#06df1bf91b8af07964dca314a6031b32">dump</a> (int fd, const Vector< String16 > &args) const =0</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Dump state of the camera hardware. <a href="#06df1bf91b8af07964dca314a6031b32"></a><br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+<a class="el" href="_camera_hardware_interface_8h.html">CameraHardwareInterface.h</a> defines the interface to the camera hardware abstraction layer, used for setting and getting parameters, live previewing, and taking pictures.
+<p>
+It is a referenced counted interface with RefBase as its base class. CameraService calls <a class="el" href="namespaceandroid.html#24c243f7f9ba0d1d881be17ae06254a2" title="factory function to instantiate a camera hardware object">openCameraHardware()</a> to retrieve a strong pointer to the instance of this interface and may be called multiple times. The following steps describe a typical sequence:<p>
+<ol type=1>
+<li>After CameraService calls <a class="el" href="namespaceandroid.html#24c243f7f9ba0d1d881be17ae06254a2" title="factory function to instantiate a camera hardware object">openCameraHardware()</a>, <a class="el" href="classandroid_1_1_camera_hardware_interface.html#4c748a3c0aa3c5f2333e0abcdbeb15cb" title="Return the camera parameters.">getParameters()</a> and <a class="el" href="classandroid_1_1_camera_hardware_interface.html#82e54ede14bd263274bbc8777bafc384" title="Set the camera parameters.">setParameters()</a> are used to initialize the camera instance. CameraService calls <a class="el" href="classandroid_1_1_camera_hardware_interface.html#9d4071fb234a0c2e7bf6ea78e723f2f4" title="Return the IMemoryHeap for the preview image heap.">getPreviewHeap()</a> to establish access to the preview heap so it can be registered with SurfaceFlinger for efficient display updating while in preview mode.</li><li><a class="el" href="classandroid_1_1_camera_hardware_interface.html#62def8031dee8bdab7933770708a6312" title="Start preview mode.">startPreview()</a> is called, which is passed a <a class="el" href="namespaceandroid.html#d32b08663d42356404e2eb971e271636" title="Callback for startPreview().">preview_callback()</a> function and a user parameter. The camera instance then periodically calls <a class="el" href="namespaceandroid.html#d32b08663d42356404e2eb971e271636" title="Callback for startPreview().">preview_callback()</a> each time a new preview frame is available. The callback routine has two parameters: the first is a pointer to the IMemory containing the frame and the second a user parameter. If the preview_callback code needs to use this memory after returning, it must copy the data.</li></ol>
+<p>
+Prior to taking a picture, CameraService calls autofocus() with <a class="el" href="namespaceandroid.html#4dca8d8b824ca9a684358133da0ec8f2" title="Callback for autoFocus().">autofocus_callback()</a> and a user parameter. When auto focusing has completed, the camera instance calls <a class="el" href="namespaceandroid.html#4dca8d8b824ca9a684358133da0ec8f2" title="Callback for autoFocus().">autofocus_callback()</a>, which informs the application whether focusing was successful. The camera instance only calls <a class="el" href="namespaceandroid.html#4dca8d8b824ca9a684358133da0ec8f2" title="Callback for autoFocus().">autofocus_callback()</a> once and it is up to the application to call <a class="el" href="classandroid_1_1_camera_hardware_interface.html#0dda73938e9b18326dd48bd721dbd515" title="Start auto focus, the callback routine is called once when focusing is complete.">autoFocus()</a> again if refocusing is desired.<p>
+CameraService calls <a class="el" href="classandroid_1_1_camera_hardware_interface.html#2aedf65cad695ce439029f37a7cb66c4" title="Take a picture.">takePicture()</a> to request the camera instance take a picture. This method has two callbacks: <a class="el" href="namespaceandroid.html#a97926709e452d66360cb9b24736969e" title="Callback for takePicture().">raw_callback()</a> and <a class="el" href="namespaceandroid.html#c21980d4be1e0cc458399ecf5374d473" title="Callback for takePicture().">jpeg_callback()</a>. When the raw image is available, <a class="el" href="namespaceandroid.html#a97926709e452d66360cb9b24736969e" title="Callback for takePicture().">raw_callback()</a> is called with a pointer to the IMemory containing the raw image. When the jpeg image is available, <a class="el" href="namespaceandroid.html#c21980d4be1e0cc458399ecf5374d473" title="Callback for takePicture().">jpeg_callback()</a> is called with a pointer to the IMemory containing the jpeg image. As with <a class="el" href="namespaceandroid.html#d32b08663d42356404e2eb971e271636" title="Callback for startPreview().">preview_callback()</a>, the memory must be copied if it's needed after returning.
+<p>Definition at line <a class="el" href="_camera_hardware_interface_8h-source.html#l00079">79</a> of file <a class="el" href="_camera_hardware_interface_8h-source.html">CameraHardwareInterface.h</a>.</p>
+<hr><h2>Constructor & Destructor Documentation</h2>
+<a class="anchor" name="99f4ab74b58cd4b23e0fb00a46a60cb1"></a><!-- doxytag: member="android::CameraHardwareInterface::~CameraHardwareInterface" ref="99f4ab74b58cd4b23e0fb00a46a60cb1" args="()" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual android::CameraHardwareInterface::~CameraHardwareInterface </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td><code> [inline, virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+
+<p>Definition at line <a class="el" href="_camera_hardware_interface_8h-source.html#l00081">81</a> of file <a class="el" href="_camera_hardware_interface_8h-source.html">CameraHardwareInterface.h</a>.</p>
+
+</div>
+</div><p>
+<hr><h2>Member Function Documentation</h2>
+<a class="anchor" name="9d4071fb234a0c2e7bf6ea78e723f2f4"></a><!-- doxytag: member="android::CameraHardwareInterface::getPreviewHeap" ref="9d4071fb234a0c2e7bf6ea78e723f2f4" args="() const =0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual sp<IMemoryHeap> android::CameraHardwareInterface::getPreviewHeap </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td> const<code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Return the IMemoryHeap for the preview image heap.
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="62def8031dee8bdab7933770708a6312"></a><!-- doxytag: member="android::CameraHardwareInterface::startPreview" ref="62def8031dee8bdab7933770708a6312" args="(preview_callback cb, void *user)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::CameraHardwareInterface::startPreview </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="namespaceandroid.html#d32b08663d42356404e2eb971e271636">preview_callback</a> </td>
+ <td class="paramname"> <em>cb</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">void * </td>
+ <td class="paramname"> <em>user</em></td><td> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Start preview mode.
+<p>
+When a preview image is available preview_callback is called with the user parameter. The call back parameter may be null.
+</div>
+</div><p>
+<a class="anchor" name="34faa77065f415b93cb1acf84fc788bf"></a><!-- doxytag: member="android::CameraHardwareInterface::stopPreview" ref="34faa77065f415b93cb1acf84fc788bf" args="()=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual void android::CameraHardwareInterface::stopPreview </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Stop a previously started preview.
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="0dda73938e9b18326dd48bd721dbd515"></a><!-- doxytag: member="android::CameraHardwareInterface::autoFocus" ref="0dda73938e9b18326dd48bd721dbd515" args="(autofocus_callback, void *user)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::CameraHardwareInterface::autoFocus </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="namespaceandroid.html#4dca8d8b824ca9a684358133da0ec8f2">autofocus_callback</a> </td>
+ <td class="paramname">, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">void * </td>
+ <td class="paramname"> <em>user</em></td><td> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Start auto focus, the callback routine is called once when focusing is complete.
+<p>
+<a class="el" href="classandroid_1_1_camera_hardware_interface.html#0dda73938e9b18326dd48bd721dbd515" title="Start auto focus, the callback routine is called once when focusing is complete.">autoFocus()</a> will be called again if another auto focus is needed.
+</div>
+</div><p>
+<a class="anchor" name="2aedf65cad695ce439029f37a7cb66c4"></a><!-- doxytag: member="android::CameraHardwareInterface::takePicture" ref="2aedf65cad695ce439029f37a7cb66c4" args="(shutter_callback, raw_callback, jpeg_callback, void *user)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::CameraHardwareInterface::takePicture </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="namespaceandroid.html#04c83209c2627e2d303320712ca9ee65">shutter_callback</a> </td>
+ <td class="paramname">, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="namespaceandroid.html#a97926709e452d66360cb9b24736969e">raw_callback</a> </td>
+ <td class="paramname">, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="namespaceandroid.html#c21980d4be1e0cc458399ecf5374d473">jpeg_callback</a> </td>
+ <td class="paramname">, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">void * </td>
+ <td class="paramname"> <em>user</em></td><td> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Take a picture.
+<p>
+The raw_callback is called when the uncompressed image is available. The jpeg_callback is called when the compressed image is available. These call backs may be null. The user parameter is passed to each of the call back routines.
+</div>
+</div><p>
+<a class="anchor" name="da8faf376215a605357d26afa1b79386"></a><!-- doxytag: member="android::CameraHardwareInterface::cancelPicture" ref="da8faf376215a605357d26afa1b79386" args="(bool cancel_shutter, bool cancel_raw, bool cancel_jpeg)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::CameraHardwareInterface::cancelPicture </td>
+ <td>(</td>
+ <td class="paramtype">bool </td>
+ <td class="paramname"> <em>cancel_shutter</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">bool </td>
+ <td class="paramname"> <em>cancel_raw</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">bool </td>
+ <td class="paramname"> <em>cancel_jpeg</em></td><td> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Cancel a picture that was started with takePicture.
+<p>
+You may cancel any of the shutter, raw, or jpeg callbacks. Calling this method when no picture is being taken is a no-op.
+</div>
+</div><p>
+<a class="anchor" name="82e54ede14bd263274bbc8777bafc384"></a><!-- doxytag: member="android::CameraHardwareInterface::setParameters" ref="82e54ede14bd263274bbc8777bafc384" args="(const CameraParameters &params)=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::CameraHardwareInterface::setParameters </td>
+ <td>(</td>
+ <td class="paramtype">const CameraParameters & </td>
+ <td class="paramname"> <em>params</em> </td>
+ <td> ) </td>
+ <td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the camera parameters.
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="4c748a3c0aa3c5f2333e0abcdbeb15cb"></a><!-- doxytag: member="android::CameraHardwareInterface::getParameters" ref="4c748a3c0aa3c5f2333e0abcdbeb15cb" args="() const =0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual CameraParameters android::CameraHardwareInterface::getParameters </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td> const<code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Return the camera parameters.
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="df65310b8aa176e0ce5f08b87d6b7eb8"></a><!-- doxytag: member="android::CameraHardwareInterface::release" ref="df65310b8aa176e0ce5f08b87d6b7eb8" args="()=0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual void android::CameraHardwareInterface::release </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td><code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Release the hardware resources owned by this object.
+<p>
+Note that this is *not* done in the destructor.
+</div>
+</div><p>
+<a class="anchor" name="06df1bf91b8af07964dca314a6031b32"></a><!-- doxytag: member="android::CameraHardwareInterface::dump" ref="06df1bf91b8af07964dca314a6031b32" args="(int fd, const Vector< String16 > &args) const =0" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">virtual status_t android::CameraHardwareInterface::dump </td>
+ <td>(</td>
+ <td class="paramtype">int </td>
+ <td class="paramname"> <em>fd</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const Vector< String16 > & </td>
+ <td class="paramname"> <em>args</em></td><td> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td> const<code> [pure virtual]</code></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Dump state of the camera hardware.
+<p>
+
+</div>
+</div><p>
+<hr>The documentation for this class was generated from the following file:<ul>
+<li><a class="el" href="_camera_hardware_interface_8h-source.html">CameraHardwareInterface.h</a></ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/display_drivers.html b/pdk/docs/display_drivers.html
index eb4d31a..c20afe5 100755
--- a/pdk/docs/display_drivers.html
+++ b/pdk/docs/display_drivers.html
@@ -2,11 +2,23 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
-<title>Android - Display Drivers</title>
+<title>Android - Porting Guide</title>
<script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=internal-codesite" type="text/javascript"></script>
<script src="http://code.google.com/js/jquery.js" type="text/javascript"></script>
<script type="text/javascript">var _tocPath_ = 'http://code.google.com/android/_toc.ezt';</script>
<script src="http://code.google.com/js/codesite.pack.01312008.js" type="text/javascript"></script>
+<script language="JavaScript">
+function resizeHeight() {
+ if(document.getElementById && !(document.all)) {
+ height= document.getElementById('doxygen').contentDocument.body.scrollHeight + 20;
+ document.getElementById('doxygen').style.height = height;
+ }
+ else if(document.all) {
+ height= document.frames('doxygen').document.body.scrollHeight + 20;
+ document.all.doxygen.style.height = height;
+ }
+}
+</script>
<link href="http://code.google.com/css/codesite.pack.01312008.css" type="text/css" rel="stylesheet">
</link>
@@ -33,6 +45,7 @@
<div id="skipto"> </div>
<div id="langpref">
<!--<a class="dropdown" href="/">English</a> <span>|</span> <a href="/more/">Site Directory</a> -->
+
</div>
<div id="gc-header">
<div id="logo"><a href="http://code.google.com/android/index.html"><img src="http://code.google.com/android/images/logo_android.gif" alt="Android"/></a></div>
@@ -51,6 +64,7 @@
}
</style>
</noscript>
+
<div id="searchForm2" class="searchForm2" style="display:none">
<form id="searchbox_001456098540849067467:6whlsytkdqg" action="http://www.google.com/cse">
<input type="hidden" name="cx" value="001456098540849067467:6whlsytkdqg" />
@@ -59,6 +73,7 @@
<input type="submit" name="sa" value="Search" title="Search"/>
<br/>
<div class="greytext">e.g. "ajax apis" or "open source"</div>
+
</form>
</div>
<!-- end searchForm2 -->
@@ -71,15 +86,18 @@
<div id="codesiteContent">
<a name="gc-topnav-anchor"></a>
<div id="gc-topnav">
+
<h1>Android Platform Development Kit</h1>
<ul class="gc-topnav-tabs">
<li id="sdk_link"> <a href="http://code.google.com/android/index.html" title="Android Software Development Kit">SDK</a> </li>
<li id="docs_link"> <a href="index.html" title="Official Android documentation">Docs</a> </li>
<li id="faq_link"> <a href="http://code.google.com/android/kb/index.html" title="Answers to frequently asked questions about Android">FAQ</a> </li>
+
<li> <a href="http://android-developers.blogspot.com/" title="Official Android blog">Blog</a> </li>
<li> <a href="http://code.google.com/android/groups.html" title="Android developer forum">Group</a> </li>
<li> <a href="http://code.google.com/android/terms.html" title="Android terms of service">Terms</a> </li>
- <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20display_drivers.html%20v0.3%20-%209%20June%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+ <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20display_drivers.html%20v0.6%20-%2025%20November%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+
</ul>
</div>
<!-- end gc-topnav -->
@@ -91,19 +109,18 @@
<h1><a href="index.html">Documentation</a></h1>
<ul>
<li> <strong>Introduction</strong>
+
<ul>
<li><a href="system_requirements.html">Device Requirements</a></li>
</ul>
</li>
<li> <strong>Dev Environment Setup</strong>
<ul>
- <li><a href="source_setup_guide.html">Host System Setup</a></li>
- <li><a href="getting_source_code.html">Getting Source Code</a></li>
- <li> <a href="intro_source_code.html">Source Code Overview</a></li>
<li><a href="build_system.html">Build System</a></li>
</ul>
</li>
<li> <strong>Basic Bring up</strong>
+
<ul>
<li><a href="build_new_device.html">Building New Device</a></li>
<li><a href="bring_up.html">Bring up</a></li>
@@ -111,26 +128,39 @@
<li><a href="display_drivers.html">Display Drivers</a></li>
</ul>
</li>
+
<li> <strong>Multimedia</strong>
<ul>
- <li><a href="audio_sub_system.html">Audio Subsystem</a></li>
+ <li><a href="audio_sub_system.html">Audio</a></li>
+ <li><a href="camera.html">Camera</a></li>
</ul>
</li>
<li> <strong>Power Management</strong>
+
<ul>
<li><a href="power_management.html">Power Management</a></li>
</ul>
</li>
+
+ <li> <strong>Networking</strong>
+ <ul>
+ <li><a href="wifi.html">Wi-Fi</a></li>
+ <li><a href="gps.html">GPS</a></li>
+ <li><a href="bluetooth.html">Bluetooth</a></li>
+ </ul>
+ </li>
+
<li> <strong>Telephony</strong>
<ul>
<li><a href="telephony.html">Radio Interface Layer</a></li>
+
</ul>
</li>
<li> <strong>Testing</strong>
<ul>
- <li><a href="instrumentation_framework.html">Instrumentation Framework</a></li>
<li><a href="instrumentation_testing.html">Instrumentation Testing</a></li>
</ul>
+
</li>
</ul>
</li>
@@ -181,7 +211,7 @@
/*
* pguidefb.c
*
- * Copyright 2007, The Android Open Source Project
+ * Copyright 2007, Google Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -508,7 +538,7 @@
pageTracker._trackPageview();
} catch(e) {}
</script>
-<div id="jd-build-id"> v0.3 - 9 June 2008</div>
+<div id="jd-build-id"> v0.6 - 25 November 2008</div>
</div></div></div></body>
</html>
diff --git a/pdk/docs/doxygen.css b/pdk/docs/doxygen.css
new file mode 100755
index 0000000..22c4843
--- /dev/null
+++ b/pdk/docs/doxygen.css
@@ -0,0 +1,473 @@
+BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+}
+BODY,TD {
+ font-size: 90%;
+}
+H1 {
+ text-align: center;
+ font-size: 160%;
+}
+H2 {
+ font-size: 120%;
+}
+H3 {
+ font-size: 100%;
+}
+CAPTION {
+ font-weight: bold
+}
+DIV.qindex {
+ width: 100%;
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ padding: 2px;
+ line-height: 140%;
+}
+DIV.navpath {
+ width: 100%;
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ padding: 2px;
+ line-height: 140%;
+}
+DIV.navtab {
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ margin-right: 15px;
+ padding: 2px;
+}
+TD.navtab {
+ font-size: 70%;
+}
+A.qindex {
+ text-decoration: none;
+ font-weight: bold;
+ color: #1A419D;
+}
+A.qindex:visited {
+ text-decoration: none;
+ font-weight: bold;
+ color: #1A419D
+}
+A.qindex:hover {
+ text-decoration: none;
+ background-color: #ddddff;
+}
+A.qindexHL {
+ text-decoration: none;
+ font-weight: bold;
+ background-color: #6666cc;
+ color: #ffffff;
+ border: 1px double #9295C2;
+}
+A.qindexHL:hover {
+ text-decoration: none;
+ background-color: #6666cc;
+ color: #ffffff;
+}
+A.qindexHL:visited {
+ text-decoration: none;
+ background-color: #6666cc;
+ color: #ffffff
+}
+A.el {
+ text-decoration: none;
+ font-weight: bold
+}
+A.elRef {
+ font-weight: bold
+}
+A.code:link {
+ text-decoration: none;
+ font-weight: normal;
+ color: #0000FF
+}
+A.code:visited {
+ text-decoration: none;
+ font-weight: normal;
+ color: #0000FF
+}
+A.codeRef:link {
+ font-weight: normal;
+ color: #0000FF
+}
+A.codeRef:visited {
+ font-weight: normal;
+ color: #0000FF
+}
+A:hover {
+ text-decoration: none;
+ background-color: #f2f2ff
+}
+DL.el {
+ margin-left: -1cm
+}
+.fragment {
+ font-family: monospace, fixed;
+ font-size: 95%;
+}
+PRE.fragment {
+ border: 1px solid #CCCCCC;
+ background-color: #f5f5f5;
+ margin-top: 4px;
+ margin-bottom: 4px;
+ margin-left: 2px;
+ margin-right: 8px;
+ padding-left: 6px;
+ padding-right: 6px;
+ padding-top: 4px;
+ padding-bottom: 4px;
+}
+DIV.ah {
+ background-color: black;
+ font-weight: bold;
+ color: #ffffff;
+ margin-bottom: 3px;
+ margin-top: 3px
+}
+
+DIV.groupHeader {
+ margin-left: 16px;
+ margin-top: 12px;
+ margin-bottom: 6px;
+ font-weight: bold;
+}
+DIV.groupText {
+ margin-left: 16px;
+ font-style: italic;
+ font-size: 90%
+}
+BODY {
+ background: white;
+ color: black;
+ margin-right: 20px;
+ margin-left: 20px;
+}
+TD.indexkey {
+ background-color: #e8eef2;
+ font-weight: bold;
+ padding-right : 10px;
+ padding-top : 2px;
+ padding-left : 10px;
+ padding-bottom : 2px;
+ margin-left : 0px;
+ margin-right : 0px;
+ margin-top : 2px;
+ margin-bottom : 2px;
+ border: 1px solid #CCCCCC;
+}
+TD.indexvalue {
+ background-color: #e8eef2;
+ font-style: italic;
+ padding-right : 10px;
+ padding-top : 2px;
+ padding-left : 10px;
+ padding-bottom : 2px;
+ margin-left : 0px;
+ margin-right : 0px;
+ margin-top : 2px;
+ margin-bottom : 2px;
+ border: 1px solid #CCCCCC;
+}
+TR.memlist {
+ background-color: #f0f0f0;
+}
+P.formulaDsp {
+ text-align: center;
+}
+IMG.formulaDsp {
+}
+IMG.formulaInl {
+ vertical-align: middle;
+}
+SPAN.keyword { color: #008000 }
+SPAN.keywordtype { color: #604020 }
+SPAN.keywordflow { color: #e08000 }
+SPAN.comment { color: #800000 }
+SPAN.preprocessor { color: #806020 }
+SPAN.stringliteral { color: #002080 }
+SPAN.charliteral { color: #008080 }
+SPAN.vhdldigit { color: #ff00ff }
+SPAN.vhdlchar { color: #000000 }
+SPAN.vhdlkeyword { color: #700070 }
+SPAN.vhdllogic { color: #ff0000 }
+
+.mdescLeft {
+ padding: 0px 8px 4px 8px;
+ font-size: 80%;
+ font-style: italic;
+ background-color: #FAFAFA;
+ border-top: 1px none #E0E0E0;
+ border-right: 1px none #E0E0E0;
+ border-bottom: 1px none #E0E0E0;
+ border-left: 1px none #E0E0E0;
+ margin: 0px;
+}
+.mdescRight {
+ padding: 0px 8px 4px 8px;
+ font-size: 80%;
+ font-style: italic;
+ background-color: #FAFAFA;
+ border-top: 1px none #E0E0E0;
+ border-right: 1px none #E0E0E0;
+ border-bottom: 1px none #E0E0E0;
+ border-left: 1px none #E0E0E0;
+ margin: 0px;
+}
+.memItemLeft {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: solid;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memItemRight {
+ padding: 1px 8px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: solid;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memTemplItemLeft {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: none;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memTemplItemRight {
+ padding: 1px 8px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: none;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memTemplParams {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: solid;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ color: #606060;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.search {
+ color: #003399;
+ font-weight: bold;
+}
+FORM.search {
+ margin-bottom: 0px;
+ margin-top: 0px;
+}
+INPUT.search {
+ font-size: 75%;
+ color: #000080;
+ font-weight: normal;
+ background-color: #e8eef2;
+}
+TD.tiny {
+ font-size: 75%;
+}
+a {
+ color: #1A41A8;
+}
+a:visited {
+ color: #2A3798;
+}
+.dirtab {
+ padding: 4px;
+ border-collapse: collapse;
+ border: 1px solid #84b0c7;
+}
+TH.dirtab {
+ background: #e8eef2;
+ font-weight: bold;
+}
+HR {
+ height: 1px;
+ border: none;
+ border-top: 1px solid black;
+}
+
+/* Style for detailed member documentation */
+.memtemplate {
+ font-size: 80%;
+ color: #606060;
+ font-weight: normal;
+ margin-left: 3px;
+}
+.memnav {
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ margin-right: 15px;
+ padding: 2px;
+}
+.memitem {
+ padding: 4px;
+ background-color: #eef3f5;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #dedeee;
+ -moz-border-radius: 8px 8px 8px 8px;
+}
+.memname {
+ white-space: nowrap;
+ font-weight: bold;
+}
+.memdoc{
+ padding-left: 10px;
+}
+.memproto {
+ background-color: #d5e1e8;
+ width: 100%;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #84b0c7;
+ font-weight: bold;
+ -moz-border-radius: 8px 8px 8px 8px;
+}
+.paramkey {
+ text-align: right;
+}
+.paramtype {
+ white-space: nowrap;
+}
+.paramname {
+ color: #602020;
+ font-style: italic;
+ white-space: nowrap;
+}
+/* End Styling for detailed member documentation */
+
+/* for the tree view */
+.ftvtree {
+ font-family: sans-serif;
+ margin:0.5em;
+}
+/* these are for tree view when used as main index */
+.directory {
+ font-size: 9pt;
+ font-weight: bold;
+}
+.directory h3 {
+ margin: 0px;
+ margin-top: 1em;
+ font-size: 11pt;
+}
+
+/* The following two styles can be used to replace the root node title */
+/* with an image of your choice. Simply uncomment the next two styles, */
+/* specify the name of your image and be sure to set 'height' to the */
+/* proper pixel height of your image. */
+
+/* .directory h3.swap { */
+/* height: 61px; */
+/* background-repeat: no-repeat; */
+/* background-image: url("yourimage.gif"); */
+/* } */
+/* .directory h3.swap span { */
+/* display: none; */
+/* } */
+
+.directory > h3 {
+ margin-top: 0;
+}
+.directory p {
+ margin: 0px;
+ white-space: nowrap;
+}
+.directory div {
+ display: none;
+ margin: 0px;
+}
+.directory img {
+ vertical-align: -30%;
+}
+/* these are for tree view when not used as main index */
+.directory-alt {
+ font-size: 100%;
+ font-weight: bold;
+}
+.directory-alt h3 {
+ margin: 0px;
+ margin-top: 1em;
+ font-size: 11pt;
+}
+.directory-alt > h3 {
+ margin-top: 0;
+}
+.directory-alt p {
+ margin: 0px;
+ white-space: nowrap;
+}
+.directory-alt div {
+ display: none;
+ margin: 0px;
+}
+.directory-alt img {
+ vertical-align: -30%;
+}
+
diff --git a/pdk/docs/doxygen.png b/pdk/docs/doxygen.png
new file mode 100755
index 0000000..f0a274b
--- /dev/null
+++ b/pdk/docs/doxygen.png
Binary files differ
diff --git a/pdk/docs/files.html b/pdk/docs/files.html
new file mode 100755
index 0000000..ec75239
--- /dev/null
+++ b/pdk/docs/files.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li class="current"><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li class="current"><a href="files.html"><span>File List</span></a></li>
+ <li><a href="globals.html"><span>Globals</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+<h1>File List</h1>Here is a list of all files with brief descriptions:<table>
+ <tr><td class="indexkey"><a class="el" href="_audio_hardware_interface_8h.html">AudioHardwareInterface.h</a> <a href="_audio_hardware_interface_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><a class="el" href="_camera_hardware_interface_8h.html">CameraHardwareInterface.h</a> <a href="_camera_hardware_interface_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><a class="el" href="gps_8h.html">gps.h</a> <a href="gps_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><a class="el" href="wifi_8h.html">wifi.h</a> <a href="wifi_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/functions.html b/pdk/docs/functions.html
new file mode 100755
index 0000000..c31d517
--- /dev/null
+++ b/pdk/docs/functions.html
@@ -0,0 +1,258 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li class="current"><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li class="current"><a href="functions.html"><span>Data Fields</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li class="current"><a href="functions.html"><span>All</span></a></li>
+ <li><a href="functions_func.html"><span>Functions</span></a></li>
+ <li><a href="functions_vars.html"><span>Variables</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="#index_a"><span>a</span></a></li>
+ <li><a href="#index_b"><span>b</span></a></li>
+ <li><a href="#index_c"><span>c</span></a></li>
+ <li><a href="#index_d"><span>d</span></a></li>
+ <li><a href="#index_e"><span>e</span></a></li>
+ <li><a href="#index_f"><span>f</span></a></li>
+ <li><a href="#index_g"><span>g</span></a></li>
+ <li><a href="#index_i"><span>i</span></a></li>
+ <li><a href="#index_l"><span>l</span></a></li>
+ <li><a href="#index_n"><span>n</span></a></li>
+ <li><a href="#index_o"><span>o</span></a></li>
+ <li><a href="#index_p"><span>p</span></a></li>
+ <li><a href="#index_r"><span>r</span></a></li>
+ <li><a href="#index_s"><span>s</span></a></li>
+ <li><a href="#index_t"><span>t</span></a></li>
+ <li><a href="#index_u"><span>u</span></a></li>
+ <li><a href="#index_w"><span>w</span></a></li>
+ <li><a href="#index_~"><span>~</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+Here is a list of all struct and union fields with links to the structures/unions they belong to:
+<p>
+<h3><a class="anchor" name="index_a">- a -</a></h3><ul>
+<li>accuracy
+: <a class="el" href="struct_gps_location.html#801ec0db8ee69fa263a63528876d773b">GpsLocation</a>
+<li>almanac_mask
+: <a class="el" href="struct_gps_sv_status.html#6ed4b741a9882ecc2852e94e8ad60310">GpsSvStatus</a>
+<li>altitude
+: <a class="el" href="struct_gps_location.html#cb3cc5ad378a6a3864e47ae67df38778">GpsLocation</a>
+<li>autoFocus()
+: <a class="el" href="classandroid_1_1_camera_hardware_interface.html#0dda73938e9b18326dd48bd721dbd515">android::CameraHardwareInterface</a>
+<li>azimuth
+: <a class="el" href="struct_gps_sv_info.html#94755ad36e31a012269459d5a4ef0594">GpsSvInfo</a>
+</ul>
+<h3><a class="anchor" name="index_b">- b -</a></h3><ul>
+<li>bearing
+: <a class="el" href="struct_gps_location.html#b71bf9b61cf55f10ffcf34ba1654d082">GpsLocation</a>
+<li>bufferSize()
+: <a class="el" href="classandroid_1_1_audio_stream_in.html#a458f9cde3edde82f256af7eaa7b2ddf">android::AudioStreamIn</a>
+, <a class="el" href="classandroid_1_1_audio_stream_out.html#7b3c5f2ce79b9b6f167408f63d19af0a">android::AudioStreamOut</a>
+</ul>
+<h3><a class="anchor" name="index_c">- c -</a></h3><ul>
+<li>cancelPicture()
+: <a class="el" href="classandroid_1_1_camera_hardware_interface.html#da8faf376215a605357d26afa1b79386">android::CameraHardwareInterface</a>
+<li>channelCount()
+: <a class="el" href="classandroid_1_1_audio_stream_out.html#4e880a5379c168e8f68c26827e41275b">android::AudioStreamOut</a>
+, <a class="el" href="classandroid_1_1_audio_stream_in.html#04f84006dd5f2e0a5e512897a039f851">android::AudioStreamIn</a>
+<li>cleanup
+: <a class="el" href="struct_gps_interface.html#2911808e36c70259dc0db162de02dc13">GpsInterface</a>
+<li>create()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#aa5ae45e9ad969fefc494e103cf5068d">android::AudioHardwareInterface</a>
+</ul>
+<h3><a class="anchor" name="index_d">- d -</a></h3><ul>
+<li>delete_aiding_data
+: <a class="el" href="struct_gps_interface.html#a3a9b81a8a719b628ac8049344f50b58">GpsInterface</a>
+<li>doRouting()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#d82c3e4827f275abf28eb872e8751e1f">android::AudioHardwareInterface</a>
+<li>download_request_cb
+: <a class="el" href="struct_gps_xtra_callbacks.html#7e879ba4c3e32c52eaa0fb04fb9c226f">GpsXtraCallbacks</a>
+<li>dump()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#371f198a416cb726804e0f47e8763217">android::AudioHardwareInterface</a>
+, <a class="el" href="classandroid_1_1_audio_stream_in.html#18c3760208bfb99498715a0d4977f675">android::AudioStreamIn</a>
+, <a class="el" href="classandroid_1_1_audio_stream_out.html#97e3cc4610ba40d6c37b3d376a032b98">android::AudioStreamOut</a>
+, <a class="el" href="classandroid_1_1_camera_hardware_interface.html#06df1bf91b8af07964dca314a6031b32">android::CameraHardwareInterface</a>
+<li>dumpState()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#05f035af60e67a22251175b44a089f69">android::AudioHardwareInterface</a>
+</ul>
+<h3><a class="anchor" name="index_e">- e -</a></h3><ul>
+<li>elevation
+: <a class="el" href="struct_gps_sv_info.html#0634009d0476b2f06f27568b0722a04d">GpsSvInfo</a>
+<li>ephemeris_mask
+: <a class="el" href="struct_gps_sv_status.html#4751f70f8e275241dece99db0df4ab5b">GpsSvStatus</a>
+</ul>
+<h3><a class="anchor" name="index_f">- f -</a></h3><ul>
+<li>flags
+: <a class="el" href="struct_gps_location.html#07d55fee34dc28cff50062e9ac42c717">GpsLocation</a>
+<li>format()
+: <a class="el" href="classandroid_1_1_audio_stream_out.html#eb2b430bbff4eebd8fb8590507b1dce1">android::AudioStreamOut</a>
+, <a class="el" href="classandroid_1_1_audio_stream_in.html#4ade98c5243b9ed5f3a71a8f36e74b36">android::AudioStreamIn</a>
+<li>frameSize()
+: <a class="el" href="classandroid_1_1_audio_stream_out.html#66b7c4bb510db4060adfd03a376897d8">android::AudioStreamOut</a>
+, <a class="el" href="classandroid_1_1_audio_stream_in.html#43d2c6b97806c005f0717a7bb6f7595c">android::AudioStreamIn</a>
+</ul>
+<h3><a class="anchor" name="index_g">- g -</a></h3><ul>
+<li>get_extension
+: <a class="el" href="struct_gps_interface.html#19af32bd9d01ebbcdb196e36514b0e98">GpsInterface</a>
+<li>getInputBufferSize()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#19f68d873b2a6e4c00c017c580170395">android::AudioHardwareInterface</a>
+<li>getMicMute()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#15d3c33d7e3f965dc2588c537f05a133">android::AudioHardwareInterface</a>
+<li>getMode()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#8466c76328a51b8a83da103032abba55">android::AudioHardwareInterface</a>
+<li>getParameters()
+: <a class="el" href="classandroid_1_1_camera_hardware_interface.html#4c748a3c0aa3c5f2333e0abcdbeb15cb">android::CameraHardwareInterface</a>
+<li>getPreviewHeap()
+: <a class="el" href="classandroid_1_1_camera_hardware_interface.html#9d4071fb234a0c2e7bf6ea78e723f2f4">android::CameraHardwareInterface</a>
+<li>getRouting()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#1886de8fff2342ae628dbbbc0c45ba83">android::AudioHardwareInterface</a>
+</ul>
+<h3><a class="anchor" name="index_i">- i -</a></h3><ul>
+<li>init
+: <a class="el" href="struct_gps_interface.html#d5139fa13b75108bdedd8a2717f37135">GpsInterface</a>
+, <a class="el" href="struct_gps_xtra_interface.html#5532e662c68e1d3df7db86570df96bf0">GpsXtraInterface</a>
+<li>initCheck()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#b7e19e09fa6cbc07c127122fa9866c50">android::AudioHardwareInterface</a>
+<li>inject_time
+: <a class="el" href="struct_gps_interface.html#e731891e96a916271a4275eaaea47ad8">GpsInterface</a>
+<li>inject_xtra_data
+: <a class="el" href="struct_gps_xtra_interface.html#2b1962c8a5a2751702937cf469dc7435">GpsXtraInterface</a>
+</ul>
+<h3><a class="anchor" name="index_l">- l -</a></h3><ul>
+<li>latency()
+: <a class="el" href="classandroid_1_1_audio_stream_out.html#c698a3d95cf0829dcfe283cd5ea437cb">android::AudioStreamOut</a>
+<li>latitude
+: <a class="el" href="struct_gps_location.html#3a7da06efae47c66428fa2815a3eb4bd">GpsLocation</a>
+<li>location_cb
+: <a class="el" href="struct_gps_callbacks.html#1f59b4f8eeaca50620f94761536dabd3">GpsCallbacks</a>
+<li>longitude
+: <a class="el" href="struct_gps_location.html#3672d2d19087d62d7ea9b0b71418da40">GpsLocation</a>
+</ul>
+<h3><a class="anchor" name="index_n">- n -</a></h3><ul>
+<li>num_svs
+: <a class="el" href="struct_gps_sv_status.html#b90eb63a499039de996c95d98afad545">GpsSvStatus</a>
+</ul>
+<h3><a class="anchor" name="index_o">- o -</a></h3><ul>
+<li>openInputStream()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#efb777d192fcbcd65458fa4f2d976476">android::AudioHardwareInterface</a>
+<li>openOutputStream()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#eda0986e145c8dd68d21cb79051f94f9">android::AudioHardwareInterface</a>
+</ul>
+<h3><a class="anchor" name="index_p">- p -</a></h3><ul>
+<li>prn
+: <a class="el" href="struct_gps_sv_info.html#5c94e86f2efc3ed08fb5a40735a2440b">GpsSvInfo</a>
+</ul>
+<h3><a class="anchor" name="index_r">- r -</a></h3><ul>
+<li>read()
+: <a class="el" href="classandroid_1_1_audio_stream_in.html#7c313cbfbb47dafd90f3225bcd26e592">android::AudioStreamIn</a>
+<li>release()
+: <a class="el" href="classandroid_1_1_camera_hardware_interface.html#df65310b8aa176e0ce5f08b87d6b7eb8">android::CameraHardwareInterface</a>
+</ul>
+<h3><a class="anchor" name="index_s">- s -</a></h3><ul>
+<li>sampleRate()
+: <a class="el" href="classandroid_1_1_audio_stream_out.html#6bb028e125d13289f26d3d74f851c921">android::AudioStreamOut</a>
+<li>set_apn
+: <a class="el" href="struct_gps_supl_interface.html#145834775007930d644086393a6b9dce">GpsSuplInterface</a>
+<li>set_fix_frequency
+: <a class="el" href="struct_gps_interface.html#1e727f5862ae7132f12af44ebdfa76b2">GpsInterface</a>
+<li>set_position_mode
+: <a class="el" href="struct_gps_interface.html#924bff47462a773b669d310d87b75734">GpsInterface</a>
+<li>setGain()
+: <a class="el" href="classandroid_1_1_audio_stream_in.html#339822afb3f2f2ac1b4c775d31d12440">android::AudioStreamIn</a>
+<li>setMasterVolume()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#925092e556eb89f304bcebb09f90c9a3">android::AudioHardwareInterface</a>
+<li>setMicMute()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#be35b7cb738531939a3ac9abc5514621">android::AudioHardwareInterface</a>
+<li>setMode()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#aaf2a429c240f00b21836794849b430f">android::AudioHardwareInterface</a>
+<li>setParameter()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#a1b477901df48b3a27103a77e6bb39c8">android::AudioHardwareInterface</a>
+<li>setParameters()
+: <a class="el" href="classandroid_1_1_camera_hardware_interface.html#82e54ede14bd263274bbc8777bafc384">android::CameraHardwareInterface</a>
+<li>setRouting()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#39b2690e19219425b8cff093ef83bfb1">android::AudioHardwareInterface</a>
+<li>setVoiceVolume()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#7b7418072df1eeaacc89cd0c725755f6">android::AudioHardwareInterface</a>
+<li>setVolume()
+: <a class="el" href="classandroid_1_1_audio_stream_out.html#e6d301925d193c25561b42239c7f44b6">android::AudioStreamOut</a>
+<li>snr
+: <a class="el" href="struct_gps_sv_info.html#eebf16140beb95390733529bd5e7db58">GpsSvInfo</a>
+<li>speed
+: <a class="el" href="struct_gps_location.html#38ae20b9c5e7be995513dce25ed87016">GpsLocation</a>
+<li>standby()
+: <a class="el" href="classandroid_1_1_audio_stream_in.html#93fab46e8afdbaedd4d20cc6ee2b7c41">android::AudioStreamIn</a>
+, <a class="el" href="classandroid_1_1_audio_hardware_interface.html#61121d365bb4d182bdec2c1b12fb1178">android::AudioHardwareInterface</a>
+<li>start
+: <a class="el" href="struct_gps_interface.html#2b212721e0d160e24944330b2d830790">GpsInterface</a>
+<li>startPreview()
+: <a class="el" href="classandroid_1_1_camera_hardware_interface.html#62def8031dee8bdab7933770708a6312">android::CameraHardwareInterface</a>
+<li>status
+: <a class="el" href="struct_gps_status.html#64c9e8cd609d97533bee5c5e8ca78608">GpsStatus</a>
+<li>status_cb
+: <a class="el" href="struct_gps_callbacks.html#7b15a1bf4f9b989677fef84f4d8141df">GpsCallbacks</a>
+<li>stop
+: <a class="el" href="struct_gps_interface.html#d20b0cfcbf976d8cec17bf4ea0a027f1">GpsInterface</a>
+<li>stopPreview()
+: <a class="el" href="classandroid_1_1_camera_hardware_interface.html#34faa77065f415b93cb1acf84fc788bf">android::CameraHardwareInterface</a>
+<li>sv_list
+: <a class="el" href="struct_gps_sv_status.html#7a3fe2114e7a603b96fd9675adf0c5b5">GpsSvStatus</a>
+<li>sv_status_cb
+: <a class="el" href="struct_gps_callbacks.html#fb34f60ad58e80de5c04790b107bb93d">GpsCallbacks</a>
+</ul>
+<h3><a class="anchor" name="index_t">- t -</a></h3><ul>
+<li>takePicture()
+: <a class="el" href="classandroid_1_1_camera_hardware_interface.html#2aedf65cad695ce439029f37a7cb66c4">android::CameraHardwareInterface</a>
+<li>timestamp
+: <a class="el" href="struct_gps_location.html#3e16861f64869d6f0e15e4300bb2658b">GpsLocation</a>
+</ul>
+<h3><a class="anchor" name="index_u">- u -</a></h3><ul>
+<li>used_in_fix_mask
+: <a class="el" href="struct_gps_sv_status.html#9090a26639d97eec2b59bcd0446659c0">GpsSvStatus</a>
+</ul>
+<h3><a class="anchor" name="index_w">- w -</a></h3><ul>
+<li>write()
+: <a class="el" href="classandroid_1_1_audio_stream_out.html#cba177e4a4a35a87ab9f8aa2a9c0e78e">android::AudioStreamOut</a>
+</ul>
+<h3><a class="anchor" name="index_~">- ~ -</a></h3><ul>
+<li>~AudioStreamIn()
+: <a class="el" href="classandroid_1_1_audio_stream_in.html#72067577568bbdd0163c1369fe80f101">android::AudioStreamIn</a>
+<li>~AudioStreamOut()
+: <a class="el" href="classandroid_1_1_audio_stream_out.html#09074dbae95b82d4f83c513035a0034f">android::AudioStreamOut</a>
+<li>~CameraHardwareInterface()
+: <a class="el" href="classandroid_1_1_camera_hardware_interface.html#99f4ab74b58cd4b23e0fb00a46a60cb1">android::CameraHardwareInterface</a>
+</ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/functions_func.html b/pdk/docs/functions_func.html
new file mode 100755
index 0000000..2d1c1dc
--- /dev/null
+++ b/pdk/docs/functions_func.html
@@ -0,0 +1,179 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li class="current"><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li class="current"><a href="functions.html"><span>Data Fields</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="functions.html"><span>All</span></a></li>
+ <li class="current"><a href="functions_func.html"><span>Functions</span></a></li>
+ <li><a href="functions_vars.html"><span>Variables</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="#index_a"><span>a</span></a></li>
+ <li><a href="#index_b"><span>b</span></a></li>
+ <li><a href="#index_c"><span>c</span></a></li>
+ <li><a href="#index_d"><span>d</span></a></li>
+ <li><a href="#index_f"><span>f</span></a></li>
+ <li><a href="#index_g"><span>g</span></a></li>
+ <li><a href="#index_i"><span>i</span></a></li>
+ <li><a href="#index_l"><span>l</span></a></li>
+ <li><a href="#index_o"><span>o</span></a></li>
+ <li><a href="#index_r"><span>r</span></a></li>
+ <li><a href="#index_s"><span>s</span></a></li>
+ <li><a href="#index_t"><span>t</span></a></li>
+ <li><a href="#index_w"><span>w</span></a></li>
+ <li><a href="#index_~"><span>~</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+
+<p>
+<h3><a class="anchor" name="index_a">- a -</a></h3><ul>
+<li>autoFocus()
+: <a class="el" href="classandroid_1_1_camera_hardware_interface.html#0dda73938e9b18326dd48bd721dbd515">android::CameraHardwareInterface</a>
+</ul>
+<h3><a class="anchor" name="index_b">- b -</a></h3><ul>
+<li>bufferSize()
+: <a class="el" href="classandroid_1_1_audio_stream_out.html#7b3c5f2ce79b9b6f167408f63d19af0a">android::AudioStreamOut</a>
+, <a class="el" href="classandroid_1_1_audio_stream_in.html#a458f9cde3edde82f256af7eaa7b2ddf">android::AudioStreamIn</a>
+</ul>
+<h3><a class="anchor" name="index_c">- c -</a></h3><ul>
+<li>cancelPicture()
+: <a class="el" href="classandroid_1_1_camera_hardware_interface.html#da8faf376215a605357d26afa1b79386">android::CameraHardwareInterface</a>
+<li>channelCount()
+: <a class="el" href="classandroid_1_1_audio_stream_out.html#4e880a5379c168e8f68c26827e41275b">android::AudioStreamOut</a>
+, <a class="el" href="classandroid_1_1_audio_stream_in.html#04f84006dd5f2e0a5e512897a039f851">android::AudioStreamIn</a>
+<li>create()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#aa5ae45e9ad969fefc494e103cf5068d">android::AudioHardwareInterface</a>
+</ul>
+<h3><a class="anchor" name="index_d">- d -</a></h3><ul>
+<li>doRouting()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#d82c3e4827f275abf28eb872e8751e1f">android::AudioHardwareInterface</a>
+<li>dump()
+: <a class="el" href="classandroid_1_1_audio_stream_out.html#97e3cc4610ba40d6c37b3d376a032b98">android::AudioStreamOut</a>
+, <a class="el" href="classandroid_1_1_camera_hardware_interface.html#06df1bf91b8af07964dca314a6031b32">android::CameraHardwareInterface</a>
+, <a class="el" href="classandroid_1_1_audio_hardware_interface.html#371f198a416cb726804e0f47e8763217">android::AudioHardwareInterface</a>
+, <a class="el" href="classandroid_1_1_audio_stream_in.html#18c3760208bfb99498715a0d4977f675">android::AudioStreamIn</a>
+<li>dumpState()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#05f035af60e67a22251175b44a089f69">android::AudioHardwareInterface</a>
+</ul>
+<h3><a class="anchor" name="index_f">- f -</a></h3><ul>
+<li>format()
+: <a class="el" href="classandroid_1_1_audio_stream_out.html#eb2b430bbff4eebd8fb8590507b1dce1">android::AudioStreamOut</a>
+, <a class="el" href="classandroid_1_1_audio_stream_in.html#4ade98c5243b9ed5f3a71a8f36e74b36">android::AudioStreamIn</a>
+<li>frameSize()
+: <a class="el" href="classandroid_1_1_audio_stream_out.html#66b7c4bb510db4060adfd03a376897d8">android::AudioStreamOut</a>
+, <a class="el" href="classandroid_1_1_audio_stream_in.html#43d2c6b97806c005f0717a7bb6f7595c">android::AudioStreamIn</a>
+</ul>
+<h3><a class="anchor" name="index_g">- g -</a></h3><ul>
+<li>getInputBufferSize()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#19f68d873b2a6e4c00c017c580170395">android::AudioHardwareInterface</a>
+<li>getMicMute()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#15d3c33d7e3f965dc2588c537f05a133">android::AudioHardwareInterface</a>
+<li>getMode()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#8466c76328a51b8a83da103032abba55">android::AudioHardwareInterface</a>
+<li>getParameters()
+: <a class="el" href="classandroid_1_1_camera_hardware_interface.html#4c748a3c0aa3c5f2333e0abcdbeb15cb">android::CameraHardwareInterface</a>
+<li>getPreviewHeap()
+: <a class="el" href="classandroid_1_1_camera_hardware_interface.html#9d4071fb234a0c2e7bf6ea78e723f2f4">android::CameraHardwareInterface</a>
+<li>getRouting()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#1886de8fff2342ae628dbbbc0c45ba83">android::AudioHardwareInterface</a>
+</ul>
+<h3><a class="anchor" name="index_i">- i -</a></h3><ul>
+<li>initCheck()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#b7e19e09fa6cbc07c127122fa9866c50">android::AudioHardwareInterface</a>
+</ul>
+<h3><a class="anchor" name="index_l">- l -</a></h3><ul>
+<li>latency()
+: <a class="el" href="classandroid_1_1_audio_stream_out.html#c698a3d95cf0829dcfe283cd5ea437cb">android::AudioStreamOut</a>
+</ul>
+<h3><a class="anchor" name="index_o">- o -</a></h3><ul>
+<li>openInputStream()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#efb777d192fcbcd65458fa4f2d976476">android::AudioHardwareInterface</a>
+<li>openOutputStream()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#eda0986e145c8dd68d21cb79051f94f9">android::AudioHardwareInterface</a>
+</ul>
+<h3><a class="anchor" name="index_r">- r -</a></h3><ul>
+<li>read()
+: <a class="el" href="classandroid_1_1_audio_stream_in.html#7c313cbfbb47dafd90f3225bcd26e592">android::AudioStreamIn</a>
+<li>release()
+: <a class="el" href="classandroid_1_1_camera_hardware_interface.html#df65310b8aa176e0ce5f08b87d6b7eb8">android::CameraHardwareInterface</a>
+</ul>
+<h3><a class="anchor" name="index_s">- s -</a></h3><ul>
+<li>sampleRate()
+: <a class="el" href="classandroid_1_1_audio_stream_out.html#6bb028e125d13289f26d3d74f851c921">android::AudioStreamOut</a>
+<li>setGain()
+: <a class="el" href="classandroid_1_1_audio_stream_in.html#339822afb3f2f2ac1b4c775d31d12440">android::AudioStreamIn</a>
+<li>setMasterVolume()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#925092e556eb89f304bcebb09f90c9a3">android::AudioHardwareInterface</a>
+<li>setMicMute()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#be35b7cb738531939a3ac9abc5514621">android::AudioHardwareInterface</a>
+<li>setMode()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#aaf2a429c240f00b21836794849b430f">android::AudioHardwareInterface</a>
+<li>setParameter()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#a1b477901df48b3a27103a77e6bb39c8">android::AudioHardwareInterface</a>
+<li>setParameters()
+: <a class="el" href="classandroid_1_1_camera_hardware_interface.html#82e54ede14bd263274bbc8777bafc384">android::CameraHardwareInterface</a>
+<li>setRouting()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#39b2690e19219425b8cff093ef83bfb1">android::AudioHardwareInterface</a>
+<li>setVoiceVolume()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#7b7418072df1eeaacc89cd0c725755f6">android::AudioHardwareInterface</a>
+<li>setVolume()
+: <a class="el" href="classandroid_1_1_audio_stream_out.html#e6d301925d193c25561b42239c7f44b6">android::AudioStreamOut</a>
+<li>standby()
+: <a class="el" href="classandroid_1_1_audio_hardware_interface.html#61121d365bb4d182bdec2c1b12fb1178">android::AudioHardwareInterface</a>
+, <a class="el" href="classandroid_1_1_audio_stream_in.html#93fab46e8afdbaedd4d20cc6ee2b7c41">android::AudioStreamIn</a>
+<li>startPreview()
+: <a class="el" href="classandroid_1_1_camera_hardware_interface.html#62def8031dee8bdab7933770708a6312">android::CameraHardwareInterface</a>
+<li>stopPreview()
+: <a class="el" href="classandroid_1_1_camera_hardware_interface.html#34faa77065f415b93cb1acf84fc788bf">android::CameraHardwareInterface</a>
+</ul>
+<h3><a class="anchor" name="index_t">- t -</a></h3><ul>
+<li>takePicture()
+: <a class="el" href="classandroid_1_1_camera_hardware_interface.html#2aedf65cad695ce439029f37a7cb66c4">android::CameraHardwareInterface</a>
+</ul>
+<h3><a class="anchor" name="index_w">- w -</a></h3><ul>
+<li>write()
+: <a class="el" href="classandroid_1_1_audio_stream_out.html#cba177e4a4a35a87ab9f8aa2a9c0e78e">android::AudioStreamOut</a>
+</ul>
+<h3><a class="anchor" name="index_~">- ~ -</a></h3><ul>
+<li>~AudioStreamIn()
+: <a class="el" href="classandroid_1_1_audio_stream_in.html#72067577568bbdd0163c1369fe80f101">android::AudioStreamIn</a>
+<li>~AudioStreamOut()
+: <a class="el" href="classandroid_1_1_audio_stream_out.html#09074dbae95b82d4f83c513035a0034f">android::AudioStreamOut</a>
+<li>~CameraHardwareInterface()
+: <a class="el" href="classandroid_1_1_camera_hardware_interface.html#99f4ab74b58cd4b23e0fb00a46a60cb1">android::CameraHardwareInterface</a>
+</ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/functions_vars.html b/pdk/docs/functions_vars.html
new file mode 100755
index 0000000..6d4b718
--- /dev/null
+++ b/pdk/docs/functions_vars.html
@@ -0,0 +1,158 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li class="current"><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li class="current"><a href="functions.html"><span>Data Fields</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="functions.html"><span>All</span></a></li>
+ <li><a href="functions_func.html"><span>Functions</span></a></li>
+ <li class="current"><a href="functions_vars.html"><span>Variables</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="#index_a"><span>a</span></a></li>
+ <li><a href="#index_b"><span>b</span></a></li>
+ <li><a href="#index_c"><span>c</span></a></li>
+ <li><a href="#index_d"><span>d</span></a></li>
+ <li><a href="#index_e"><span>e</span></a></li>
+ <li><a href="#index_f"><span>f</span></a></li>
+ <li><a href="#index_g"><span>g</span></a></li>
+ <li><a href="#index_i"><span>i</span></a></li>
+ <li><a href="#index_l"><span>l</span></a></li>
+ <li><a href="#index_n"><span>n</span></a></li>
+ <li><a href="#index_p"><span>p</span></a></li>
+ <li><a href="#index_s"><span>s</span></a></li>
+ <li><a href="#index_t"><span>t</span></a></li>
+ <li><a href="#index_u"><span>u</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+
+<p>
+<h3><a class="anchor" name="index_a">- a -</a></h3><ul>
+<li>accuracy
+: <a class="el" href="struct_gps_location.html#801ec0db8ee69fa263a63528876d773b">GpsLocation</a>
+<li>almanac_mask
+: <a class="el" href="struct_gps_sv_status.html#6ed4b741a9882ecc2852e94e8ad60310">GpsSvStatus</a>
+<li>altitude
+: <a class="el" href="struct_gps_location.html#cb3cc5ad378a6a3864e47ae67df38778">GpsLocation</a>
+<li>azimuth
+: <a class="el" href="struct_gps_sv_info.html#94755ad36e31a012269459d5a4ef0594">GpsSvInfo</a>
+</ul>
+<h3><a class="anchor" name="index_b">- b -</a></h3><ul>
+<li>bearing
+: <a class="el" href="struct_gps_location.html#b71bf9b61cf55f10ffcf34ba1654d082">GpsLocation</a>
+</ul>
+<h3><a class="anchor" name="index_c">- c -</a></h3><ul>
+<li>cleanup
+: <a class="el" href="struct_gps_interface.html#2911808e36c70259dc0db162de02dc13">GpsInterface</a>
+</ul>
+<h3><a class="anchor" name="index_d">- d -</a></h3><ul>
+<li>delete_aiding_data
+: <a class="el" href="struct_gps_interface.html#a3a9b81a8a719b628ac8049344f50b58">GpsInterface</a>
+<li>download_request_cb
+: <a class="el" href="struct_gps_xtra_callbacks.html#7e879ba4c3e32c52eaa0fb04fb9c226f">GpsXtraCallbacks</a>
+</ul>
+<h3><a class="anchor" name="index_e">- e -</a></h3><ul>
+<li>elevation
+: <a class="el" href="struct_gps_sv_info.html#0634009d0476b2f06f27568b0722a04d">GpsSvInfo</a>
+<li>ephemeris_mask
+: <a class="el" href="struct_gps_sv_status.html#4751f70f8e275241dece99db0df4ab5b">GpsSvStatus</a>
+</ul>
+<h3><a class="anchor" name="index_f">- f -</a></h3><ul>
+<li>flags
+: <a class="el" href="struct_gps_location.html#07d55fee34dc28cff50062e9ac42c717">GpsLocation</a>
+</ul>
+<h3><a class="anchor" name="index_g">- g -</a></h3><ul>
+<li>get_extension
+: <a class="el" href="struct_gps_interface.html#19af32bd9d01ebbcdb196e36514b0e98">GpsInterface</a>
+</ul>
+<h3><a class="anchor" name="index_i">- i -</a></h3><ul>
+<li>init
+: <a class="el" href="struct_gps_interface.html#d5139fa13b75108bdedd8a2717f37135">GpsInterface</a>
+, <a class="el" href="struct_gps_xtra_interface.html#5532e662c68e1d3df7db86570df96bf0">GpsXtraInterface</a>
+<li>inject_time
+: <a class="el" href="struct_gps_interface.html#e731891e96a916271a4275eaaea47ad8">GpsInterface</a>
+<li>inject_xtra_data
+: <a class="el" href="struct_gps_xtra_interface.html#2b1962c8a5a2751702937cf469dc7435">GpsXtraInterface</a>
+</ul>
+<h3><a class="anchor" name="index_l">- l -</a></h3><ul>
+<li>latitude
+: <a class="el" href="struct_gps_location.html#3a7da06efae47c66428fa2815a3eb4bd">GpsLocation</a>
+<li>location_cb
+: <a class="el" href="struct_gps_callbacks.html#1f59b4f8eeaca50620f94761536dabd3">GpsCallbacks</a>
+<li>longitude
+: <a class="el" href="struct_gps_location.html#3672d2d19087d62d7ea9b0b71418da40">GpsLocation</a>
+</ul>
+<h3><a class="anchor" name="index_n">- n -</a></h3><ul>
+<li>num_svs
+: <a class="el" href="struct_gps_sv_status.html#b90eb63a499039de996c95d98afad545">GpsSvStatus</a>
+</ul>
+<h3><a class="anchor" name="index_p">- p -</a></h3><ul>
+<li>prn
+: <a class="el" href="struct_gps_sv_info.html#5c94e86f2efc3ed08fb5a40735a2440b">GpsSvInfo</a>
+</ul>
+<h3><a class="anchor" name="index_s">- s -</a></h3><ul>
+<li>set_apn
+: <a class="el" href="struct_gps_supl_interface.html#145834775007930d644086393a6b9dce">GpsSuplInterface</a>
+<li>set_fix_frequency
+: <a class="el" href="struct_gps_interface.html#1e727f5862ae7132f12af44ebdfa76b2">GpsInterface</a>
+<li>set_position_mode
+: <a class="el" href="struct_gps_interface.html#924bff47462a773b669d310d87b75734">GpsInterface</a>
+<li>snr
+: <a class="el" href="struct_gps_sv_info.html#eebf16140beb95390733529bd5e7db58">GpsSvInfo</a>
+<li>speed
+: <a class="el" href="struct_gps_location.html#38ae20b9c5e7be995513dce25ed87016">GpsLocation</a>
+<li>start
+: <a class="el" href="struct_gps_interface.html#2b212721e0d160e24944330b2d830790">GpsInterface</a>
+<li>status
+: <a class="el" href="struct_gps_status.html#64c9e8cd609d97533bee5c5e8ca78608">GpsStatus</a>
+<li>status_cb
+: <a class="el" href="struct_gps_callbacks.html#7b15a1bf4f9b989677fef84f4d8141df">GpsCallbacks</a>
+<li>stop
+: <a class="el" href="struct_gps_interface.html#d20b0cfcbf976d8cec17bf4ea0a027f1">GpsInterface</a>
+<li>sv_list
+: <a class="el" href="struct_gps_sv_status.html#7a3fe2114e7a603b96fd9675adf0c5b5">GpsSvStatus</a>
+<li>sv_status_cb
+: <a class="el" href="struct_gps_callbacks.html#fb34f60ad58e80de5c04790b107bb93d">GpsCallbacks</a>
+</ul>
+<h3><a class="anchor" name="index_t">- t -</a></h3><ul>
+<li>timestamp
+: <a class="el" href="struct_gps_location.html#3e16861f64869d6f0e15e4300bb2658b">GpsLocation</a>
+</ul>
+<h3><a class="anchor" name="index_u">- u -</a></h3><ul>
+<li>used_in_fix_mask
+: <a class="el" href="struct_gps_sv_status.html#9090a26639d97eec2b59bcd0446659c0">GpsSvStatus</a>
+</ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/getting_source_code.html b/pdk/docs/getting_source_code.html
index 49bfcb0..ad0cddb 100755
--- a/pdk/docs/getting_source_code.html
+++ b/pdk/docs/getting_source_code.html
@@ -2,11 +2,23 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
-<title>Android - Getting Source Code</title>
+<title>Android - Porting Guide</title>
<script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=internal-codesite" type="text/javascript"></script>
<script src="http://code.google.com/js/jquery.js" type="text/javascript"></script>
<script type="text/javascript">var _tocPath_ = 'http://code.google.com/android/_toc.ezt';</script>
<script src="http://code.google.com/js/codesite.pack.01312008.js" type="text/javascript"></script>
+<script language="JavaScript">
+function resizeHeight() {
+ if(document.getElementById && !(document.all)) {
+ height= document.getElementById('doxygen').contentDocument.body.scrollHeight + 20;
+ document.getElementById('doxygen').style.height = height;
+ }
+ else if(document.all) {
+ height= document.frames('doxygen').document.body.scrollHeight + 20;
+ document.all.doxygen.style.height = height;
+ }
+}
+</script>
<link href="http://code.google.com/css/codesite.pack.01312008.css" type="text/css" rel="stylesheet">
</link>
@@ -33,6 +45,7 @@
<div id="skipto"> </div>
<div id="langpref">
<!--<a class="dropdown" href="/">English</a> <span>|</span> <a href="/more/">Site Directory</a> -->
+
</div>
<div id="gc-header">
<div id="logo"><a href="http://code.google.com/android/index.html"><img src="http://code.google.com/android/images/logo_android.gif" alt="Android"/></a></div>
@@ -51,6 +64,7 @@
}
</style>
</noscript>
+
<div id="searchForm2" class="searchForm2" style="display:none">
<form id="searchbox_001456098540849067467:6whlsytkdqg" action="http://www.google.com/cse">
<input type="hidden" name="cx" value="001456098540849067467:6whlsytkdqg" />
@@ -59,6 +73,7 @@
<input type="submit" name="sa" value="Search" title="Search"/>
<br/>
<div class="greytext">e.g. "ajax apis" or "open source"</div>
+
</form>
</div>
<!-- end searchForm2 -->
@@ -71,15 +86,18 @@
<div id="codesiteContent">
<a name="gc-topnav-anchor"></a>
<div id="gc-topnav">
+
<h1>Android Platform Development Kit</h1>
<ul class="gc-topnav-tabs">
<li id="sdk_link"> <a href="http://code.google.com/android/index.html" title="Android Software Development Kit">SDK</a> </li>
<li id="docs_link"> <a href="index.html" title="Official Android documentation">Docs</a> </li>
<li id="faq_link"> <a href="http://code.google.com/android/kb/index.html" title="Answers to frequently asked questions about Android">FAQ</a> </li>
+
<li> <a href="http://android-developers.blogspot.com/" title="Official Android blog">Blog</a> </li>
<li> <a href="http://code.google.com/android/groups.html" title="Android developer forum">Group</a> </li>
<li> <a href="http://code.google.com/android/terms.html" title="Android terms of service">Terms</a> </li>
- <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20getting_source_code.html%20v0.3%20-%209%20June%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+ <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20index.html%20v0.5%20-%2025%20September%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+
</ul>
</div>
<!-- end gc-topnav -->
@@ -91,6 +109,7 @@
<h1><a href="index.html">Documentation</a></h1>
<ul>
<li> <strong>Introduction</strong>
+
<ul>
<li><a href="system_requirements.html">Device Requirements</a></li>
</ul>
@@ -98,12 +117,14 @@
<li> <strong>Dev Environment Setup</strong>
<ul>
<li><a href="source_setup_guide.html">Host System Setup</a></li>
+
<li><a href="getting_source_code.html">Getting Source Code</a></li>
<li> <a href="intro_source_code.html">Source Code Overview</a></li>
<li><a href="build_system.html">Build System</a></li>
</ul>
</li>
<li> <strong>Basic Bring up</strong>
+
<ul>
<li><a href="build_new_device.html">Building New Device</a></li>
<li><a href="bring_up.html">Bring up</a></li>
@@ -111,26 +132,39 @@
<li><a href="display_drivers.html">Display Drivers</a></li>
</ul>
</li>
+
<li> <strong>Multimedia</strong>
<ul>
<li><a href="audio_sub_system.html">Audio Subsystem</a></li>
+ <li><a href="camera.html">Camera</a></li>
</ul>
</li>
<li> <strong>Power Management</strong>
+
<ul>
<li><a href="power_management.html">Power Management</a></li>
</ul>
</li>
+
+ <li> <strong>Networking</strong>
+ <ul>
+ <li><a href="wifi.html">Wi-Fi</a></li>
+ <li><a href="gps.html">GPS</a></li>
+ <li><a href="bluetooth.html">Bluetooth</a></li>
+ </ul>
+ </li>
+
<li> <strong>Telephony</strong>
<ul>
<li><a href="telephony.html">Radio Interface Layer</a></li>
+
</ul>
</li>
<li> <strong>Testing</strong>
<ul>
- <li><a href="instrumentation_framework.html">Instrumentation Framework</a></li>
<li><a href="instrumentation_testing.html">Instrumentation Testing</a></li>
</ul>
+
</li>
</ul>
</li>
@@ -295,7 +329,7 @@
pageTracker._trackPageview();
} catch(e) {}
</script>
-<div id="jd-build-id"> v0.3 - 9 June 2008</div>
+<div id="jd-build-id"> v0.5 - 25 September 2008</div>
</div></div></div></body>
</html>
diff --git a/pdk/docs/globals.html b/pdk/docs/globals.html
new file mode 100755
index 0000000..2ae967f
--- /dev/null
+++ b/pdk/docs/globals.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li class="current"><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File List</span></a></li>
+ <li class="current"><a href="globals.html"><span>Globals</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li class="current"><a href="globals.html"><span>All</span></a></li>
+ <li><a href="globals_func.html"><span>Functions</span></a></li>
+ <li><a href="globals_type.html"><span>Typedefs</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
+<p>
+<ul>
+<li>do_dhcp_request()
+: <a class="el" href="wifi_8h.html#c6876a5403aaeee922d000043a47b25a">wifi.h</a>
+<li>get_dhcp_error_string()
+: <a class="el" href="wifi_8h.html#8f25ea8ec313efb45affe65fd7c108ee">wifi.h</a>
+<li>gps_get_hardware_interface()
+: <a class="el" href="gps_8h.html#6d15bb02f1f91dd760e3e172bd7711a1">gps.h</a>
+<li>gps_get_interface()
+: <a class="el" href="gps_8h.html#b582931ddf4bafa2cc5044963be66987">gps.h</a>
+<li>gps_get_qemu_interface()
+: <a class="el" href="gps_8h.html#f73f4a220fb97545e81d82fbff54b47e">gps.h</a>
+<li>gps_location_callback
+: <a class="el" href="gps_8h.html#88f19d3da70dc0e951b51091ce0631ae">gps.h</a>
+<li>gps_status_callback
+: <a class="el" href="gps_8h.html#1d9ef60ab0b91f7c106867a6aa1e4412">gps.h</a>
+<li>gps_sv_status_callback
+: <a class="el" href="gps_8h.html#67274e784834c6c2547f4b5344fc4ea9">gps.h</a>
+<li>gps_xtra_download_request
+: <a class="el" href="gps_8h.html#08fcfb3f85c2ac3008c9c73cf9136515">gps.h</a>
+<li>GpsAidingData
+: <a class="el" href="gps_8h.html#93f0283aeabd20211499991a29db7377">gps.h</a>
+<li>GpsLocationFlags
+: <a class="el" href="gps_8h.html#4ae31616d5e232ad7a346a2d4e723e31">gps.h</a>
+<li>GpsPositionMode
+: <a class="el" href="gps_8h.html#2461a6f0dd56a1f7dc94e93207a1f740">gps.h</a>
+<li>GpsStatusValue
+: <a class="el" href="gps_8h.html#de8fa0020d3aa1748a8e26759b768ec5">gps.h</a>
+<li>GpsUtcTime
+: <a class="el" href="gps_8h.html#f2b0ea531a44c010f81a4abd27504c15">gps.h</a>
+<li>wifi_close_supplicant_connection()
+: <a class="el" href="wifi_8h.html#a3f8c99b26cfd95e90012cae63ec4826">wifi.h</a>
+<li>wifi_command()
+: <a class="el" href="wifi_8h.html#b84f92e035b7bc6a5d669b3738c93e32">wifi.h</a>
+<li>wifi_connect_to_supplicant()
+: <a class="el" href="wifi_8h.html#d81473c3f314ba581e88bb9f1ae37904">wifi.h</a>
+<li>wifi_load_driver()
+: <a class="el" href="wifi_8h.html#ef0be2b5d0603acb8e0ab99051969bb7">wifi.h</a>
+<li>wifi_start_supplicant()
+: <a class="el" href="wifi_8h.html#3372e235a7899484912d7f85887e8a47">wifi.h</a>
+<li>wifi_stop_supplicant()
+: <a class="el" href="wifi_8h.html#08b97e58f2909489f1f3d59fb31f2c19">wifi.h</a>
+<li>wifi_unload_driver()
+: <a class="el" href="wifi_8h.html#a0c054da650a0162e40f327eb05679cb">wifi.h</a>
+<li>wifi_wait_for_event()
+: <a class="el" href="wifi_8h.html#656495e1beea1e39a144cdff776cdb96">wifi.h</a>
+</ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/globals_func.html b/pdk/docs/globals_func.html
new file mode 100755
index 0000000..436cbf7
--- /dev/null
+++ b/pdk/docs/globals_func.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li class="current"><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File List</span></a></li>
+ <li class="current"><a href="globals.html"><span>Globals</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="globals.html"><span>All</span></a></li>
+ <li class="current"><a href="globals_func.html"><span>Functions</span></a></li>
+ <li><a href="globals_type.html"><span>Typedefs</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+
+<p>
+<ul>
+<li>do_dhcp_request()
+: <a class="el" href="wifi_8h.html#c6876a5403aaeee922d000043a47b25a">wifi.h</a>
+<li>get_dhcp_error_string()
+: <a class="el" href="wifi_8h.html#8f25ea8ec313efb45affe65fd7c108ee">wifi.h</a>
+<li>gps_get_hardware_interface()
+: <a class="el" href="gps_8h.html#6d15bb02f1f91dd760e3e172bd7711a1">gps.h</a>
+<li>gps_get_interface()
+: <a class="el" href="gps_8h.html#b582931ddf4bafa2cc5044963be66987">gps.h</a>
+<li>gps_get_qemu_interface()
+: <a class="el" href="gps_8h.html#f73f4a220fb97545e81d82fbff54b47e">gps.h</a>
+<li>wifi_close_supplicant_connection()
+: <a class="el" href="wifi_8h.html#a3f8c99b26cfd95e90012cae63ec4826">wifi.h</a>
+<li>wifi_command()
+: <a class="el" href="wifi_8h.html#b84f92e035b7bc6a5d669b3738c93e32">wifi.h</a>
+<li>wifi_connect_to_supplicant()
+: <a class="el" href="wifi_8h.html#d81473c3f314ba581e88bb9f1ae37904">wifi.h</a>
+<li>wifi_load_driver()
+: <a class="el" href="wifi_8h.html#ef0be2b5d0603acb8e0ab99051969bb7">wifi.h</a>
+<li>wifi_start_supplicant()
+: <a class="el" href="wifi_8h.html#3372e235a7899484912d7f85887e8a47">wifi.h</a>
+<li>wifi_stop_supplicant()
+: <a class="el" href="wifi_8h.html#08b97e58f2909489f1f3d59fb31f2c19">wifi.h</a>
+<li>wifi_unload_driver()
+: <a class="el" href="wifi_8h.html#a0c054da650a0162e40f327eb05679cb">wifi.h</a>
+<li>wifi_wait_for_event()
+: <a class="el" href="wifi_8h.html#656495e1beea1e39a144cdff776cdb96">wifi.h</a>
+</ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/globals_type.html b/pdk/docs/globals_type.html
new file mode 100755
index 0000000..ec0afbc
--- /dev/null
+++ b/pdk/docs/globals_type.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li class="current"><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File List</span></a></li>
+ <li class="current"><a href="globals.html"><span>Globals</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="globals.html"><span>All</span></a></li>
+ <li><a href="globals_func.html"><span>Functions</span></a></li>
+ <li class="current"><a href="globals_type.html"><span>Typedefs</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+
+<p>
+<ul>
+<li>gps_location_callback
+: <a class="el" href="gps_8h.html#88f19d3da70dc0e951b51091ce0631ae">gps.h</a>
+<li>gps_status_callback
+: <a class="el" href="gps_8h.html#1d9ef60ab0b91f7c106867a6aa1e4412">gps.h</a>
+<li>gps_sv_status_callback
+: <a class="el" href="gps_8h.html#67274e784834c6c2547f4b5344fc4ea9">gps.h</a>
+<li>gps_xtra_download_request
+: <a class="el" href="gps_8h.html#08fcfb3f85c2ac3008c9c73cf9136515">gps.h</a>
+<li>GpsAidingData
+: <a class="el" href="gps_8h.html#93f0283aeabd20211499991a29db7377">gps.h</a>
+<li>GpsLocationFlags
+: <a class="el" href="gps_8h.html#4ae31616d5e232ad7a346a2d4e723e31">gps.h</a>
+<li>GpsPositionMode
+: <a class="el" href="gps_8h.html#2461a6f0dd56a1f7dc94e93207a1f740">gps.h</a>
+<li>GpsStatusValue
+: <a class="el" href="gps_8h.html#de8fa0020d3aa1748a8e26759b768ec5">gps.h</a>
+<li>GpsUtcTime
+: <a class="el" href="gps_8h.html#f2b0ea531a44c010f81a4abd27504c15">gps.h</a>
+</ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/gps.html b/pdk/docs/gps.html
new file mode 100755
index 0000000..eb5473f
--- /dev/null
+++ b/pdk/docs/gps.html
@@ -0,0 +1,259 @@
+
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
+<title>Android - Porting Guide</title>
+<script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=internal-codesite" type="text/javascript"></script>
+<script src="http://code.google.com/js/jquery.js" type="text/javascript"></script>
+<script type="text/javascript">var _tocPath_ = 'http://code.google.com/android/_toc.ezt';</script>
+<script src="http://code.google.com/js/codesite.pack.01312008.js" type="text/javascript"></script>
+<script language="JavaScript">
+function resizeHeight() {
+ if(document.getElementById && !(document.all)) {
+ height= document.getElementById('doxygen').contentDocument.body.scrollHeight + 20;
+ document.getElementById('doxygen').style.height = height;
+ }
+ else if(document.all) {
+ height= document.frames('doxygen').document.body.scrollHeight + 20;
+ document.all.doxygen.style.height = height;
+ }
+}
+</script>
+<link href="http://code.google.com/css/codesite.pack.01312008.css" type="text/css" rel="stylesheet">
+</link>
+
+<!--[if IE]><link rel="stylesheet" type="text/css" href="/css/iehacks.css" /><![endif]-->
+<script src="http://code.google.com/android/assets/search_autocomplete.js"></script>
+<link rel="stylesheet" type="text/css" href="http://code.google.com/css/semantic_headers.css" />
+<link rel="stylesheet" type="text/css" href="http://code.google.com/android/assets/style.css" />
+<script>
+ jQuery(document).ready(function() {
+ jQuery("pre").addClass("prettyprint");
+ });
+ </script>
+<style type="text/css">
+<!--
+h1,h2,h3 {
+ color: #000000;
+}
+-->
+</style>
+</head>
+<body class="gc-documentation">
+<div id="gc-container">
+<a name="top"></a>
+<div id="skipto"> </div>
+<div id="langpref">
+ <!--<a class="dropdown" href="/">English</a> <span>|</span> <a href="/more/">Site Directory</a> -->
+
+</div>
+<div id="gc-header">
+ <div id="logo"><a href="http://code.google.com/android/index.html"><img src="http://code.google.com/android/images/logo_android.gif" alt="Android"/></a></div>
+ <div id="search" style="inline">
+ <div id="searchForm" class="searchForm" style="height: 44px;">
+ <!--previously form was here-->
+ </div>
+ <!-- end searchForm -->
+ <noscript>
+ <style type="text/css">
+ .searchForm {
+ display : none !important;
+ }
+ .searchForm2 {
+ display : inline !important;
+ }
+ </style>
+ </noscript>
+
+ <div id="searchForm2" class="searchForm2" style="display:none">
+ <form id="searchbox_001456098540849067467:6whlsytkdqg" action="http://www.google.com/cse">
+ <input type="hidden" name="cx" value="001456098540849067467:6whlsytkdqg" />
+ <input type="hidden" name="cof" value="FORID:0" />
+ <input type="text" name="q" maxlength="2048" size="41" autocomplete="off" title="Google Code Search"/>
+ <input type="submit" name="sa" value="Search" title="Search"/>
+ <br/>
+ <div class="greytext">e.g. "ajax apis" or "open source"</div>
+
+ </form>
+ </div>
+ <!-- end searchForm2 -->
+ </div>
+ <!-- end search -->
+</div>
+<!-- end gc-header -->
+<div id="searchControl" class="search-control"></div>
+<!--[if IE]><iframe id="backiFrame" name="backiFrame" src='/dummy.html' style="display:none"></iframe><![endif]-->
+<div id="codesiteContent">
+<a name="gc-topnav-anchor"></a>
+<div id="gc-topnav">
+
+ <h1>Android Platform Development Kit</h1>
+ <ul class="gc-topnav-tabs">
+ <li id="sdk_link"> <a href="http://code.google.com/android/index.html" title="Android Software Development Kit">SDK</a> </li>
+ <li id="docs_link"> <a href="index.html" title="Official Android documentation">Docs</a> </li>
+ <li id="faq_link"> <a href="http://code.google.com/android/kb/index.html" title="Answers to frequently asked questions about Android">FAQ</a> </li>
+
+ <li> <a href="http://android-developers.blogspot.com/" title="Official Android blog">Blog</a> </li>
+ <li> <a href="http://code.google.com/android/groups.html" title="Android developer forum">Group</a> </li>
+ <li> <a href="http://code.google.com/android/terms.html" title="Android terms of service">Terms</a> </li>
+ <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20gps.html%20v0.6%20-%2025%20November%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+
+ </ul>
+</div>
+<!-- end gc-topnav -->
+<div class="g-section g-tpl-180">
+<a name="gc-toc"></a>
+<div class="g-unit g-first" id="gc-toc">
+ <ul>
+ <li>
+ <h1><a href="index.html">Documentation</a></h1>
+ <ul>
+ <li> <strong>Introduction</strong>
+
+ <ul>
+ <li><a href="system_requirements.html">Device Requirements</a></li>
+ </ul>
+ </li>
+ <li> <strong>Dev Environment Setup</strong>
+ <ul>
+ <li><a href="build_system.html">Build System</a></li>
+ </ul>
+ </li>
+ <li> <strong>Basic Bring up</strong>
+
+ <ul>
+ <li><a href="build_new_device.html">Building New Device</a></li>
+ <li><a href="bring_up.html">Bring up</a></li>
+ <li><a href="keymaps_keyboard_input.html">Keymaps and Keyboard</a></li>
+ <li><a href="display_drivers.html">Display Drivers</a></li>
+ </ul>
+ </li>
+
+ <li> <strong>Multimedia</strong>
+ <ul>
+ <li><a href="audio_sub_system.html">Audio</a></li>
+ <li><a href="camera.html">Camera</a></li>
+ </ul>
+ </li>
+ <li> <strong>Power Management</strong>
+
+ <ul>
+ <li><a href="power_management.html">Power Management</a></li>
+ </ul>
+ </li>
+
+ <li> <strong>Networking</strong>
+ <ul>
+ <li><a href="wifi.html">Wi-Fi</a></li>
+ <li><a href="gps.html">GPS</a></li>
+ <li><a href="bluetooth.html">Bluetooth</a></li>
+ </ul>
+ </li>
+
+ <li> <strong>Telephony</strong>
+ <ul>
+ <li><a href="telephony.html">Radio Interface Layer</a></li>
+
+ </ul>
+ </li>
+ <li> <strong>Testing</strong>
+ <ul>
+ <li><a href="instrumentation_testing.html">Instrumentation Testing</a></li>
+ </ul>
+
+ </li>
+ </ul>
+ </li>
+ </ul>
+</div>
+<a name="gc-pagecontent"></a>
+<div class="g-unit" id="gc-pagecontent">
+<div id="jd-content">
+<div class="jd-descr">
+
+
+<a name="androidGpsTitle"></a><h1>GPS</h1>
+
+
+
+<a name="toc"/>
+<div style="padding:10px">
+<a href="#androidGpsIntroduction">Introduction</a><br/>
+<a href="#androidGPSBuildingDriver">Building a GPS Library</a><br/>
+<a href="#androidGPSInterface">Interface</a><br/></div></font></div>
+
+<a name="androidGpsIntroduction"></a><h2>Introduction</h2>
+
+<p>Android defines a user space C abstraction interface for GPS hardware. The interface header is defined in <code>include/hardware/gps.h</code>. In order to integate GPS with Android, you need to build a shared library that implements this interface. </p>
+
+
+<a name="androidGPSBuildingDriver"></a><h2>Building a GPS Library</h2>
+
+<p>To implement a GPS driver, create a shared library that implements the interface defined in <code>gps.h</code>. You must name your shared library <code>libgps.so</code> so that it will get loaded from <code>/system/lib</code> at runtime. Place GPS sources and Android.mk in <code>partner/acme/chipset_or_board/gps/</code> (where "acme" is your product name and "chipset_or_board" is your hardware target).</p>
+
+<p>The following stub <code>Android.mk</code> file ensures that <code>libgps</code> compiles and links to the appropriate libraries:</p>
+
+<pre class="prettify">
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libgps
+
+LOCAL_STATIC_LIBRARIES:= \
+# include any static library dependencies
+
+LOCAL_SHARED_LIBRARIES := \
+# include any shared library dependencies
+
+LOCAL_SRC_FILES += \
+# include your source files. eg. MyGpsLibrary.cpp
+
+LOCAL_CFLAGS += \
+# include any needed compile flags
+
+LOCAL_C_INCLUDES:= \
+# include any needed local header files
+
+include $(BUILD_SHARED_LIBRARY)
+</pre>
+
+
+<a name="androidGPSInterface"></a><h2>Interface</h2>
+
+
+
+<p><span class="lh2"><a name="androidDoxygenNote"></a></span>
+
+<p class="note"><strong>Note</strong>: This document relies on some Doxygen-generated content that appears in an iFrame below. To return to the Doxygen default content for this page, <a href="gps.html">click here</a>.</p>
+
+
+<iframe onLoad="resizeHeight();" src="gps_8h.html" scrolling="no" scroll="no" id="doxygen" marginwidth="0" marginheight="0" frameborder="0" style="width:100%;"></iframe>
+
+
+ </div>
+ </div>
+ <!-- end gc-pagecontent -->
+ </div>
+ <!-- end gooey wrapper -->
+ </div>
+ <!-- end codesearchresults -->
+ <div id="gc-footer" dir="ltr">
+ <div class="text"> ©2008 Google<!-- - <a href="/">Code Home</a> - <a href="http://www.google.com/accounts/TOS">Site Terms of Service</a> - <a href="http://www.google.com/privacy.html">Privacy Policy</a> - <a href="/more">Site Directory</a> --></div>
+ </div>
+ <!-- end gc-footer -->
+</div>
+<!-- end gc-containter -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-18071-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+<div id="jd-build-id"> v0.6 - 25 November 2008</div>
+</div></div></div></body>
+</html>
+
diff --git a/pdk/docs/gps_8h-source.html b/pdk/docs/gps_8h-source.html
new file mode 100755
index 0000000..dbf6a16
--- /dev/null
+++ b/pdk/docs/gps_8h-source.html
@@ -0,0 +1,298 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li class="current"><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+</div>
+<h1>gps.h</h1><a href="gps_8h.html">Go to the documentation of this file.</a><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*</span>
+<a name="l00002"></a>00002 <span class="comment"> * Copyright (C) 2008 The Android Open Source Project</span>
+<a name="l00003"></a>00003 <span class="comment"> *</span>
+<a name="l00004"></a>00004 <span class="comment"> * Licensed under the Apache License, Version 2.0 (the "License");</span>
+<a name="l00005"></a>00005 <span class="comment"> * you may not use this file except in compliance with the License.</span>
+<a name="l00006"></a>00006 <span class="comment"> * You may obtain a copy of the License at</span>
+<a name="l00007"></a>00007 <span class="comment"> *</span>
+<a name="l00008"></a>00008 <span class="comment"> * http://www.apache.org/licenses/LICENSE-2.0</span>
+<a name="l00009"></a>00009 <span class="comment"> *</span>
+<a name="l00010"></a>00010 <span class="comment"> * Unless required by applicable law or agreed to in writing, software</span>
+<a name="l00011"></a>00011 <span class="comment"> * distributed under the License is distributed on an "AS IS" BASIS,</span>
+<a name="l00012"></a>00012 <span class="comment"> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span>
+<a name="l00013"></a>00013 <span class="comment"> * See the License for the specific language governing permissions and</span>
+<a name="l00014"></a>00014 <span class="comment"> * limitations under the License.</span>
+<a name="l00015"></a>00015 <span class="comment"> */</span>
+<a name="l00016"></a>00016
+<a name="l00017"></a>00017 <span class="preprocessor">#ifndef _HARDWARE_GPS_H</span>
+<a name="l00018"></a>00018 <span class="preprocessor"></span><span class="preprocessor">#define _HARDWARE_GPS_H</span>
+<a name="l00019"></a>00019 <span class="preprocessor"></span>
+<a name="l00020"></a>00020 <span class="preprocessor">#include <stdint.h></span>
+<a name="l00021"></a>00021
+<a name="l00022"></a>00022 <span class="preprocessor">#if __cplusplus</span>
+<a name="l00023"></a>00023 <span class="preprocessor"></span><span class="keyword">extern</span> <span class="stringliteral">"C"</span> {
+<a name="l00024"></a>00024 <span class="preprocessor">#endif</span>
+<a name="l00025"></a>00025 <span class="preprocessor"></span><span class="comment"></span>
+<a name="l00026"></a>00026 <span class="comment">/** Milliseconds since January 1, 1970 */</span>
+<a name="l00027"></a><a class="code" href="gps_8h.html#f2b0ea531a44c010f81a4abd27504c15">00027</a> <span class="keyword">typedef</span> int64_t <a class="code" href="gps_8h.html#f2b0ea531a44c010f81a4abd27504c15" title="Milliseconds since January 1, 1970.">GpsUtcTime</a>;
+<a name="l00028"></a>00028 <span class="comment"></span>
+<a name="l00029"></a>00029 <span class="comment">/** Maximum number of SVs for gps_sv_status_callback(). */</span>
+<a name="l00030"></a>00030 <span class="preprocessor">#define GPS_MAX_SVS 32</span>
+<a name="l00031"></a>00031 <span class="preprocessor"></span><span class="comment"></span>
+<a name="l00032"></a>00032 <span class="comment">/** Requested mode for GPS operation. */</span>
+<a name="l00033"></a><a class="code" href="gps_8h.html#2461a6f0dd56a1f7dc94e93207a1f740">00033</a> <span class="keyword">typedef</span> uint16_t <a class="code" href="gps_8h.html#2461a6f0dd56a1f7dc94e93207a1f740" title="Requested mode for GPS operation.">GpsPositionMode</a>;
+<a name="l00034"></a>00034 <span class="comment">// IMPORTANT: Note that the following values must match</span>
+<a name="l00035"></a>00035 <span class="comment">// constants in GpsLocationProvider.java.</span><span class="comment"></span>
+<a name="l00036"></a>00036 <span class="comment">/** Mode for running GPS standalone (no assistance). */</span>
+<a name="l00037"></a>00037 <span class="preprocessor">#define GPS_POSITION_MODE_STANDALONE 0</span>
+<a name="l00038"></a>00038 <span class="preprocessor"></span><span class="comment">/** SUPL MS-Based mode. */</span>
+<a name="l00039"></a>00039 <span class="preprocessor">#define GPS_POSITION_MODE_MS_BASED 1</span>
+<a name="l00040"></a>00040 <span class="preprocessor"></span><span class="comment">/** SUPL MS-Assisted mode. */</span>
+<a name="l00041"></a>00041 <span class="preprocessor">#define GPS_POSITION_MODE_MS_ASSISTED 2</span>
+<a name="l00042"></a>00042 <span class="preprocessor"></span><span class="comment"></span>
+<a name="l00043"></a>00043 <span class="comment">/** GPS status event values. */</span>
+<a name="l00044"></a><a class="code" href="gps_8h.html#de8fa0020d3aa1748a8e26759b768ec5">00044</a> <span class="keyword">typedef</span> uint16_t <a class="code" href="gps_8h.html#de8fa0020d3aa1748a8e26759b768ec5" title="GPS status event values.">GpsStatusValue</a>;
+<a name="l00045"></a>00045 <span class="comment">// IMPORTANT: Note that the following values must match</span>
+<a name="l00046"></a>00046 <span class="comment">// constants in GpsLocationProvider.java.</span><span class="comment"></span>
+<a name="l00047"></a>00047 <span class="comment">/** GPS status unknown. */</span>
+<a name="l00048"></a>00048 <span class="preprocessor">#define GPS_STATUS_NONE 0</span>
+<a name="l00049"></a>00049 <span class="preprocessor"></span><span class="comment">/** GPS has begun navigating. */</span>
+<a name="l00050"></a>00050 <span class="preprocessor">#define GPS_STATUS_SESSION_BEGIN 1</span>
+<a name="l00051"></a>00051 <span class="preprocessor"></span><span class="comment">/** GPS has stopped navigating. */</span>
+<a name="l00052"></a>00052 <span class="preprocessor">#define GPS_STATUS_SESSION_END 2</span>
+<a name="l00053"></a>00053 <span class="preprocessor"></span><span class="comment">/** GPS has powered on but is not navigating. */</span>
+<a name="l00054"></a>00054 <span class="preprocessor">#define GPS_STATUS_ENGINE_ON 3</span>
+<a name="l00055"></a>00055 <span class="preprocessor"></span><span class="comment">/** GPS is powered off. */</span>
+<a name="l00056"></a>00056 <span class="preprocessor">#define GPS_STATUS_ENGINE_OFF 4</span>
+<a name="l00057"></a>00057 <span class="preprocessor"></span><span class="comment"></span>
+<a name="l00058"></a>00058 <span class="comment">/** Flags to indicate which values are valid in a GpsLocation. */</span>
+<a name="l00059"></a><a class="code" href="gps_8h.html#4ae31616d5e232ad7a346a2d4e723e31">00059</a> <span class="keyword">typedef</span> uint16_t <a class="code" href="gps_8h.html#4ae31616d5e232ad7a346a2d4e723e31" title="Flags to indicate which values are valid in a GpsLocation.">GpsLocationFlags</a>;
+<a name="l00060"></a>00060 <span class="comment">// IMPORTANT: Note that the following values must match</span>
+<a name="l00061"></a>00061 <span class="comment">// constants in GpsLocationProvider.java.</span><span class="comment"></span>
+<a name="l00062"></a>00062 <span class="comment">/** GpsLocation has valid latitude and longitude. */</span>
+<a name="l00063"></a>00063 <span class="preprocessor">#define GPS_LOCATION_HAS_LAT_LONG 0x0001</span>
+<a name="l00064"></a>00064 <span class="preprocessor"></span><span class="comment">/** GpsLocation has valid altitude. */</span>
+<a name="l00065"></a>00065 <span class="preprocessor">#define GPS_LOCATION_HAS_ALTITUDE 0x0002</span>
+<a name="l00066"></a>00066 <span class="preprocessor"></span><span class="comment">/** GpsLocation has valid speed. */</span>
+<a name="l00067"></a>00067 <span class="preprocessor">#define GPS_LOCATION_HAS_SPEED 0x0004</span>
+<a name="l00068"></a>00068 <span class="preprocessor"></span><span class="comment">/** GpsLocation has valid bearing. */</span>
+<a name="l00069"></a>00069 <span class="preprocessor">#define GPS_LOCATION_HAS_BEARING 0x0008</span>
+<a name="l00070"></a>00070 <span class="preprocessor"></span><span class="comment">/** GpsLocation has valid accuracy. */</span>
+<a name="l00071"></a>00071 <span class="preprocessor">#define GPS_LOCATION_HAS_ACCURACY 0x0010</span>
+<a name="l00072"></a>00072 <span class="preprocessor"></span><span class="comment"></span>
+<a name="l00073"></a>00073 <span class="comment">/** Flags used to specify which aiding data to delete</span>
+<a name="l00074"></a>00074 <span class="comment"> when calling delete_aiding_data(). */</span>
+<a name="l00075"></a><a class="code" href="gps_8h.html#93f0283aeabd20211499991a29db7377">00075</a> <span class="keyword">typedef</span> uint16_t <a class="code" href="gps_8h.html#93f0283aeabd20211499991a29db7377" title="Flags used to specify which aiding data to delete when calling delete_aiding_data()...">GpsAidingData</a>;
+<a name="l00076"></a>00076 <span class="comment">// IMPORTANT: Note that the following values must match</span>
+<a name="l00077"></a>00077 <span class="comment">// constants in GpsLocationProvider.java.</span>
+<a name="l00078"></a>00078 <span class="preprocessor">#define GPS_DELETE_EPHEMERIS 0x0001</span>
+<a name="l00079"></a>00079 <span class="preprocessor"></span><span class="preprocessor">#define GPS_DELETE_ALMANAC 0x0002</span>
+<a name="l00080"></a>00080 <span class="preprocessor"></span><span class="preprocessor">#define GPS_DELETE_POSITION 0x0004</span>
+<a name="l00081"></a>00081 <span class="preprocessor"></span><span class="preprocessor">#define GPS_DELETE_TIME 0x0008</span>
+<a name="l00082"></a>00082 <span class="preprocessor"></span><span class="preprocessor">#define GPS_DELETE_IONO 0x0010</span>
+<a name="l00083"></a>00083 <span class="preprocessor"></span><span class="preprocessor">#define GPS_DELETE_UTC 0x0020</span>
+<a name="l00084"></a>00084 <span class="preprocessor"></span><span class="preprocessor">#define GPS_DELETE_HEALTH 0x0040</span>
+<a name="l00085"></a>00085 <span class="preprocessor"></span><span class="preprocessor">#define GPS_DELETE_SVDIR 0x0080</span>
+<a name="l00086"></a>00086 <span class="preprocessor"></span><span class="preprocessor">#define GPS_DELETE_SVSTEER 0x0100</span>
+<a name="l00087"></a>00087 <span class="preprocessor"></span><span class="preprocessor">#define GPS_DELETE_SADATA 0x0200</span>
+<a name="l00088"></a>00088 <span class="preprocessor"></span><span class="preprocessor">#define GPS_DELETE_RTI 0x0400</span>
+<a name="l00089"></a>00089 <span class="preprocessor"></span><span class="preprocessor">#define GPS_DELETE_CELLDB_INFO 0x8000</span>
+<a name="l00090"></a>00090 <span class="preprocessor"></span><span class="preprocessor">#define GPS_DELETE_ALL 0xFFFF</span>
+<a name="l00091"></a>00091 <span class="preprocessor"></span><span class="comment"></span>
+<a name="l00092"></a>00092 <span class="comment">/**</span>
+<a name="l00093"></a>00093 <span class="comment"> * Name for the GPS XTRA interface.</span>
+<a name="l00094"></a>00094 <span class="comment"> */</span>
+<a name="l00095"></a>00095 <span class="preprocessor">#define GPS_XTRA_INTERFACE "gps-xtra"</span>
+<a name="l00096"></a>00096 <span class="preprocessor"></span><span class="comment"></span>
+<a name="l00097"></a>00097 <span class="comment">/**</span>
+<a name="l00098"></a>00098 <span class="comment"> * Name for the GPS SUPL interface.</span>
+<a name="l00099"></a>00099 <span class="comment"> */</span>
+<a name="l00100"></a>00100 <span class="preprocessor">#define GPS_SUPL_INTERFACE "gps-supl"</span>
+<a name="l00101"></a>00101 <span class="preprocessor"></span><span class="comment"></span>
+<a name="l00102"></a>00102 <span class="comment">/** Represents a location. */</span>
+<a name="l00103"></a><a class="code" href="struct_gps_location.html">00103</a> <span class="keyword">typedef</span> <span class="keyword">struct </span>{<span class="comment"></span>
+<a name="l00104"></a>00104 <span class="comment"> /** Contains GpsLocationFlags bits. */</span>
+<a name="l00105"></a><a class="code" href="struct_gps_location.html#07d55fee34dc28cff50062e9ac42c717">00105</a> uint16_t flags;<span class="comment"></span>
+<a name="l00106"></a>00106 <span class="comment"> /** Represents latitude in degrees. */</span>
+<a name="l00107"></a><a class="code" href="struct_gps_location.html#3a7da06efae47c66428fa2815a3eb4bd">00107</a> <span class="keywordtype">double</span> latitude;<span class="comment"></span>
+<a name="l00108"></a>00108 <span class="comment"> /** Represents longitude in degrees. */</span>
+<a name="l00109"></a><a class="code" href="struct_gps_location.html#3672d2d19087d62d7ea9b0b71418da40">00109</a> <span class="keywordtype">double</span> longitude;<span class="comment"></span>
+<a name="l00110"></a>00110 <span class="comment"> /** Represents altitude in meters above the WGS 84 reference</span>
+<a name="l00111"></a>00111 <span class="comment"> * ellipsoid. */</span>
+<a name="l00112"></a><a class="code" href="struct_gps_location.html#cb3cc5ad378a6a3864e47ae67df38778">00112</a> <span class="keywordtype">double</span> altitude;<span class="comment"></span>
+<a name="l00113"></a>00113 <span class="comment"> /** Represents speed in meters per second. */</span>
+<a name="l00114"></a><a class="code" href="struct_gps_location.html#38ae20b9c5e7be995513dce25ed87016">00114</a> <span class="keywordtype">float</span> speed;<span class="comment"></span>
+<a name="l00115"></a>00115 <span class="comment"> /** Represents heading in degrees. */</span>
+<a name="l00116"></a><a class="code" href="struct_gps_location.html#b71bf9b61cf55f10ffcf34ba1654d082">00116</a> <span class="keywordtype">float</span> bearing;<span class="comment"></span>
+<a name="l00117"></a>00117 <span class="comment"> /** Represents expected accuracy in meters. */</span>
+<a name="l00118"></a><a class="code" href="struct_gps_location.html#801ec0db8ee69fa263a63528876d773b">00118</a> <span class="keywordtype">float</span> accuracy;<span class="comment"></span>
+<a name="l00119"></a>00119 <span class="comment"> /** Timestamp for the location fix. */</span>
+<a name="l00120"></a><a class="code" href="struct_gps_location.html#3e16861f64869d6f0e15e4300bb2658b">00120</a> GpsUtcTime timestamp;
+<a name="l00121"></a>00121 } <a class="code" href="struct_gps_location.html" title="Represents a location.">GpsLocation</a>;
+<a name="l00122"></a>00122 <span class="comment"></span>
+<a name="l00123"></a>00123 <span class="comment">/** Represents the status. */</span>
+<a name="l00124"></a><a class="code" href="struct_gps_status.html">00124</a> <span class="keyword">typedef</span> <span class="keyword">struct </span>{
+<a name="l00125"></a><a class="code" href="struct_gps_status.html#64c9e8cd609d97533bee5c5e8ca78608">00125</a> GpsStatusValue status;
+<a name="l00126"></a>00126 } <a class="code" href="struct_gps_status.html" title="Represents the status.">GpsStatus</a>;
+<a name="l00127"></a>00127 <span class="comment"></span>
+<a name="l00128"></a>00128 <span class="comment">/** Represents SV information. */</span>
+<a name="l00129"></a><a class="code" href="struct_gps_sv_info.html">00129</a> <span class="keyword">typedef</span> <span class="keyword">struct </span>{<span class="comment"></span>
+<a name="l00130"></a>00130 <span class="comment"> /** Pseudo-random number for the SV. */</span>
+<a name="l00131"></a><a class="code" href="struct_gps_sv_info.html#5c94e86f2efc3ed08fb5a40735a2440b">00131</a> <span class="keywordtype">int</span> prn;<span class="comment"></span>
+<a name="l00132"></a>00132 <span class="comment"> /** Signal to noise ratio. */</span>
+<a name="l00133"></a><a class="code" href="struct_gps_sv_info.html#eebf16140beb95390733529bd5e7db58">00133</a> <span class="keywordtype">float</span> snr;<span class="comment"></span>
+<a name="l00134"></a>00134 <span class="comment"> /** Elevation of SV in degrees. */</span>
+<a name="l00135"></a><a class="code" href="struct_gps_sv_info.html#0634009d0476b2f06f27568b0722a04d">00135</a> <span class="keywordtype">float</span> elevation;<span class="comment"></span>
+<a name="l00136"></a>00136 <span class="comment"> /** Azimuth of SV in degrees. */</span>
+<a name="l00137"></a><a class="code" href="struct_gps_sv_info.html#94755ad36e31a012269459d5a4ef0594">00137</a> <span class="keywordtype">float</span> azimuth;
+<a name="l00138"></a>00138 } <a class="code" href="struct_gps_sv_info.html" title="Represents SV information.">GpsSvInfo</a>;
+<a name="l00139"></a>00139 <span class="comment"></span>
+<a name="l00140"></a>00140 <span class="comment">/** Represents SV status. */</span>
+<a name="l00141"></a><a class="code" href="struct_gps_sv_status.html">00141</a> <span class="keyword">typedef</span> <span class="keyword">struct </span>{<span class="comment"></span>
+<a name="l00142"></a>00142 <span class="comment"> /** Number of SVs currently visible. */</span>
+<a name="l00143"></a><a class="code" href="struct_gps_sv_status.html#b90eb63a499039de996c95d98afad545">00143</a> <span class="keywordtype">int</span> num_svs;
+<a name="l00144"></a>00144 <span class="comment"></span>
+<a name="l00145"></a>00145 <span class="comment"> /** Contains an array of SV information. */</span>
+<a name="l00146"></a><a class="code" href="struct_gps_sv_status.html#7a3fe2114e7a603b96fd9675adf0c5b5">00146</a> <a class="code" href="struct_gps_sv_info.html" title="Represents SV information.">GpsSvInfo</a> sv_list[GPS_MAX_SVS];
+<a name="l00147"></a>00147 <span class="comment"></span>
+<a name="l00148"></a>00148 <span class="comment"> /** Represents a bit mask indicating which SVs</span>
+<a name="l00149"></a>00149 <span class="comment"> * have ephemeris data.</span>
+<a name="l00150"></a>00150 <span class="comment"> */</span>
+<a name="l00151"></a><a class="code" href="struct_gps_sv_status.html#4751f70f8e275241dece99db0df4ab5b">00151</a> uint32_t ephemeris_mask;
+<a name="l00152"></a>00152 <span class="comment"></span>
+<a name="l00153"></a>00153 <span class="comment"> /** Represents a bit mask indicating which SVs</span>
+<a name="l00154"></a>00154 <span class="comment"> * have almanac data.</span>
+<a name="l00155"></a>00155 <span class="comment"> */</span>
+<a name="l00156"></a><a class="code" href="struct_gps_sv_status.html#6ed4b741a9882ecc2852e94e8ad60310">00156</a> uint32_t almanac_mask;
+<a name="l00157"></a>00157 <span class="comment"></span>
+<a name="l00158"></a>00158 <span class="comment"> /**</span>
+<a name="l00159"></a>00159 <span class="comment"> * Represents a bit mask indicating which SVs</span>
+<a name="l00160"></a>00160 <span class="comment"> * were used for computing the most recent position fix.</span>
+<a name="l00161"></a>00161 <span class="comment"> */</span>
+<a name="l00162"></a><a class="code" href="struct_gps_sv_status.html#9090a26639d97eec2b59bcd0446659c0">00162</a> uint32_t used_in_fix_mask;
+<a name="l00163"></a>00163 } <a class="code" href="struct_gps_sv_status.html" title="Represents SV status.">GpsSvStatus</a>;
+<a name="l00164"></a>00164 <span class="comment"></span>
+<a name="l00165"></a>00165 <span class="comment">/** Callback with location information. */</span>
+<a name="l00166"></a><a class="code" href="gps_8h.html#88f19d3da70dc0e951b51091ce0631ae">00166</a> <span class="keyword">typedef</span> void (* <a class="code" href="gps_8h.html#88f19d3da70dc0e951b51091ce0631ae" title="Callback with location information.">gps_location_callback</a>)(<a class="code" href="struct_gps_location.html" title="Represents a location.">GpsLocation</a>* location);
+<a name="l00167"></a>00167 <span class="comment"></span>
+<a name="l00168"></a>00168 <span class="comment">/** Callback with status information. */</span>
+<a name="l00169"></a><a class="code" href="gps_8h.html#1d9ef60ab0b91f7c106867a6aa1e4412">00169</a> <span class="keyword">typedef</span> void (* <a class="code" href="gps_8h.html#1d9ef60ab0b91f7c106867a6aa1e4412" title="Callback with status information.">gps_status_callback</a>)(<a class="code" href="struct_gps_status.html" title="Represents the status.">GpsStatus</a>* status);
+<a name="l00170"></a>00170 <span class="comment"></span>
+<a name="l00171"></a>00171 <span class="comment">/** Callback with SV status information. */</span>
+<a name="l00172"></a><a class="code" href="gps_8h.html#67274e784834c6c2547f4b5344fc4ea9">00172</a> <span class="keyword">typedef</span> void (* <a class="code" href="gps_8h.html#67274e784834c6c2547f4b5344fc4ea9" title="Callback with SV status information.">gps_sv_status_callback</a>)(<a class="code" href="struct_gps_sv_status.html" title="Represents SV status.">GpsSvStatus</a>* sv_info);
+<a name="l00173"></a>00173 <span class="comment"></span>
+<a name="l00174"></a>00174 <span class="comment">/** GPS callback structure. */</span>
+<a name="l00175"></a><a class="code" href="struct_gps_callbacks.html">00175</a> <span class="keyword">typedef</span> <span class="keyword">struct </span>{
+<a name="l00176"></a><a class="code" href="struct_gps_callbacks.html#1f59b4f8eeaca50620f94761536dabd3">00176</a> <a class="code" href="gps_8h.html#88f19d3da70dc0e951b51091ce0631ae" title="Callback with location information.">gps_location_callback</a> location_cb;
+<a name="l00177"></a><a class="code" href="struct_gps_callbacks.html#7b15a1bf4f9b989677fef84f4d8141df">00177</a> <a class="code" href="gps_8h.html#1d9ef60ab0b91f7c106867a6aa1e4412" title="Callback with status information.">gps_status_callback</a> status_cb;
+<a name="l00178"></a><a class="code" href="struct_gps_callbacks.html#fb34f60ad58e80de5c04790b107bb93d">00178</a> <a class="code" href="gps_8h.html#67274e784834c6c2547f4b5344fc4ea9" title="Callback with SV status information.">gps_sv_status_callback</a> sv_status_cb;
+<a name="l00179"></a>00179 } <a class="code" href="struct_gps_callbacks.html" title="GPS callback structure.">GpsCallbacks</a>;
+<a name="l00180"></a>00180
+<a name="l00181"></a>00181 <span class="comment"></span>
+<a name="l00182"></a>00182 <span class="comment">/** Represents the standard GPS interface. */</span>
+<a name="l00183"></a><a class="code" href="struct_gps_interface.html">00183</a> <span class="keyword">typedef</span> <span class="keyword">struct </span>{<span class="comment"></span>
+<a name="l00184"></a>00184 <span class="comment"> /**</span>
+<a name="l00185"></a>00185 <span class="comment"> * Opens the interface and provides the callback routines</span>
+<a name="l00186"></a>00186 <span class="comment"> * to the implemenation of this interface.</span>
+<a name="l00187"></a>00187 <span class="comment"> */</span>
+<a name="l00188"></a>00188 int (*init)( <a class="code" href="struct_gps_callbacks.html" title="GPS callback structure.">GpsCallbacks</a>* callbacks );
+<a name="l00189"></a>00189 <span class="comment"></span>
+<a name="l00190"></a>00190 <span class="comment"> /** Starts navigating. */</span>
+<a name="l00191"></a>00191 int (*start)( void );
+<a name="l00192"></a>00192 <span class="comment"></span>
+<a name="l00193"></a>00193 <span class="comment"> /** Stops navigating. */</span>
+<a name="l00194"></a>00194 int (*stop)( void );
+<a name="l00195"></a>00195 <span class="comment"></span>
+<a name="l00196"></a>00196 <span class="comment"> /** Sets requested frequency of fixes in seconds. */</span>
+<a name="l00197"></a>00197 void (*set_fix_frequency)( <span class="keywordtype">int</span> frequency );
+<a name="l00198"></a>00198 <span class="comment"></span>
+<a name="l00199"></a>00199 <span class="comment"> /** Closes the interface. */</span>
+<a name="l00200"></a>00200 void (*cleanup)( void );
+<a name="l00201"></a>00201 <span class="comment"></span>
+<a name="l00202"></a>00202 <span class="comment"> /** Injects the current time. */</span>
+<a name="l00203"></a>00203 int (*inject_time)(GpsUtcTime time, int64_t timeReference,
+<a name="l00204"></a>00204 <span class="keywordtype">int</span> uncertainty);
+<a name="l00205"></a>00205 <span class="comment"></span>
+<a name="l00206"></a>00206 <span class="comment"> /**</span>
+<a name="l00207"></a>00207 <span class="comment"> * Specifies that the next call to start will not use the</span>
+<a name="l00208"></a>00208 <span class="comment"> * information defined in the flags. GPS_DELETE_ALL is passed for</span>
+<a name="l00209"></a>00209 <span class="comment"> * a cold start.</span>
+<a name="l00210"></a>00210 <span class="comment"> */</span>
+<a name="l00211"></a>00211 void (*delete_aiding_data)(GpsAidingData flags);
+<a name="l00212"></a>00212 <span class="comment"></span>
+<a name="l00213"></a>00213 <span class="comment"> /**</span>
+<a name="l00214"></a>00214 <span class="comment"> * fix_frequency represents the time between fixes in seconds.</span>
+<a name="l00215"></a>00215 <span class="comment"> * Set fix_frequency to zero for a single-shot fix.</span>
+<a name="l00216"></a>00216 <span class="comment"> */</span>
+<a name="l00217"></a>00217 int (*set_position_mode)(GpsPositionMode mode, <span class="keywordtype">int</span> fix_frequency);
+<a name="l00218"></a>00218 <span class="comment"></span>
+<a name="l00219"></a>00219 <span class="comment"> /** Get a pointer to extension information. */</span>
+<a name="l00220"></a>00220 <span class="keyword">const</span> <span class="keywordtype">void</span>* (*get_extension)(<span class="keyword">const</span> <span class="keywordtype">char</span>* name);
+<a name="l00221"></a>00221 } <a class="code" href="struct_gps_interface.html" title="Represents the standard GPS interface.">GpsInterface</a>;
+<a name="l00222"></a>00222 <span class="comment"></span>
+<a name="l00223"></a>00223 <span class="comment">/** Callback to request the client to download XTRA data.</span>
+<a name="l00224"></a>00224 <span class="comment"> The client should download XTRA data and inject it by calling</span>
+<a name="l00225"></a>00225 <span class="comment"> inject_xtra_data(). */</span>
+<a name="l00226"></a><a class="code" href="gps_8h.html#08fcfb3f85c2ac3008c9c73cf9136515">00226</a> <span class="keyword">typedef</span> void (* <a class="code" href="gps_8h.html#08fcfb3f85c2ac3008c9c73cf9136515" title="Callback to request the client to download XTRA data.">gps_xtra_download_request</a>)();
+<a name="l00227"></a>00227 <span class="comment"></span>
+<a name="l00228"></a>00228 <span class="comment">/** Callback structure for the XTRA interface. */</span>
+<a name="l00229"></a><a class="code" href="struct_gps_xtra_callbacks.html">00229</a> <span class="keyword">typedef</span> <span class="keyword">struct </span>{
+<a name="l00230"></a><a class="code" href="struct_gps_xtra_callbacks.html#7e879ba4c3e32c52eaa0fb04fb9c226f">00230</a> <a class="code" href="gps_8h.html#08fcfb3f85c2ac3008c9c73cf9136515" title="Callback to request the client to download XTRA data.">gps_xtra_download_request</a> download_request_cb;
+<a name="l00231"></a>00231 } <a class="code" href="struct_gps_xtra_callbacks.html" title="Callback structure for the XTRA interface.">GpsXtraCallbacks</a>;
+<a name="l00232"></a>00232 <span class="comment"></span>
+<a name="l00233"></a>00233 <span class="comment">/** Extended interface for XTRA support. */</span>
+<a name="l00234"></a><a class="code" href="struct_gps_xtra_interface.html">00234</a> <span class="keyword">typedef</span> <span class="keyword">struct </span>{<span class="comment"></span>
+<a name="l00235"></a>00235 <span class="comment"> /**</span>
+<a name="l00236"></a>00236 <span class="comment"> * Opens the XTRA interface and provides the callback routines</span>
+<a name="l00237"></a>00237 <span class="comment"> * to the implemenation of this interface.</span>
+<a name="l00238"></a>00238 <span class="comment"> */</span>
+<a name="l00239"></a>00239 int (*init)( <a class="code" href="struct_gps_xtra_callbacks.html" title="Callback structure for the XTRA interface.">GpsXtraCallbacks</a>* callbacks );<span class="comment"></span>
+<a name="l00240"></a>00240 <span class="comment"> /** Injects XTRA data into the GPS. */</span>
+<a name="l00241"></a>00241 int (*inject_xtra_data)( <span class="keywordtype">char</span>* data, <span class="keywordtype">int</span> length );
+<a name="l00242"></a>00242 } <a class="code" href="struct_gps_xtra_interface.html" title="Extended interface for XTRA support.">GpsXtraInterface</a>;
+<a name="l00243"></a>00243 <span class="comment"></span>
+<a name="l00244"></a>00244 <span class="comment">/** Extended interface for SUPL support. */</span>
+<a name="l00245"></a><a class="code" href="struct_gps_supl_interface.html">00245</a> <span class="keyword">typedef</span> <span class="keyword">struct </span>{<span class="comment"></span>
+<a name="l00246"></a>00246 <span class="comment"> /**</span>
+<a name="l00247"></a>00247 <span class="comment"> * Sets the name of the APN to be used for SUPL.</span>
+<a name="l00248"></a>00248 <span class="comment"> */</span>
+<a name="l00249"></a>00249 int (*set_apn)( <span class="keyword">const</span> <span class="keywordtype">char</span>* apn );
+<a name="l00250"></a>00250 } <a class="code" href="struct_gps_supl_interface.html" title="Extended interface for SUPL support.">GpsSuplInterface</a>;
+<a name="l00251"></a>00251 <span class="comment"></span>
+<a name="l00252"></a>00252 <span class="comment">/** Returns the hardware GPS interface. */</span>
+<a name="l00253"></a>00253 <span class="keyword">const</span> <a class="code" href="struct_gps_interface.html" title="Represents the standard GPS interface.">GpsInterface</a>* <a class="code" href="gps_8h.html#6d15bb02f1f91dd760e3e172bd7711a1" title="Returns the hardware GPS interface.">gps_get_hardware_interface</a>();
+<a name="l00254"></a>00254 <span class="comment"></span>
+<a name="l00255"></a>00255 <span class="comment">/**</span>
+<a name="l00256"></a>00256 <span class="comment"> * Returns the qemu emulated GPS interface.</span>
+<a name="l00257"></a>00257 <span class="comment"> */</span>
+<a name="l00258"></a>00258 <span class="keyword">const</span> <a class="code" href="struct_gps_interface.html" title="Represents the standard GPS interface.">GpsInterface</a>* <a class="code" href="gps_8h.html#f73f4a220fb97545e81d82fbff54b47e" title="Returns the qemu emulated GPS interface.">gps_get_qemu_interface</a>();
+<a name="l00259"></a>00259 <span class="comment"></span>
+<a name="l00260"></a>00260 <span class="comment">/**</span>
+<a name="l00261"></a>00261 <span class="comment"> * Returns the default GPS interface.</span>
+<a name="l00262"></a>00262 <span class="comment"> */</span>
+<a name="l00263"></a>00263 <span class="keyword">const</span> <a class="code" href="struct_gps_interface.html" title="Represents the standard GPS interface.">GpsInterface</a>* <a class="code" href="gps_8h.html#b582931ddf4bafa2cc5044963be66987" title="Returns the default GPS interface.">gps_get_interface</a>();
+<a name="l00264"></a>00264
+<a name="l00265"></a>00265 <span class="preprocessor">#if __cplusplus</span>
+<a name="l00266"></a>00266 <span class="preprocessor"></span>} <span class="comment">// extern "C"</span>
+<a name="l00267"></a>00267 <span class="preprocessor">#endif</span>
+<a name="l00268"></a>00268 <span class="preprocessor"></span>
+<a name="l00269"></a>00269 <span class="preprocessor">#endif // _HARDWARE_GPS_H</span>
+</pre></div></div>
+</body>
+</html>
diff --git a/pdk/docs/gps_8h.html b/pdk/docs/gps_8h.html
new file mode 100755
index 0000000..726d25e
--- /dev/null
+++ b/pdk/docs/gps_8h.html
@@ -0,0 +1,337 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li class="current"><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+<h1>gps.h File Reference</h1>
+<p>
+<a href="gps_8h-source.html">Go to the source code of this file.</a><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Data Structures</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">struct </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_location.html">GpsLocation</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Represents a location. <a href="struct_gps_location.html#_details">More...</a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">struct </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_status.html">GpsStatus</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Represents the status. <a href="struct_gps_status.html#_details">More...</a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">struct </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_sv_info.html">GpsSvInfo</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Represents SV information. <a href="struct_gps_sv_info.html#_details">More...</a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">struct </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_sv_status.html">GpsSvStatus</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Represents SV status. <a href="struct_gps_sv_status.html#_details">More...</a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">struct </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_callbacks.html">GpsCallbacks</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">GPS callback structure. <a href="struct_gps_callbacks.html#_details">More...</a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">struct </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_interface.html">GpsInterface</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Represents the standard GPS interface. <a href="struct_gps_interface.html#_details">More...</a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">struct </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_xtra_callbacks.html">GpsXtraCallbacks</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Callback structure for the XTRA interface. <a href="struct_gps_xtra_callbacks.html#_details">More...</a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">struct </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_xtra_interface.html">GpsXtraInterface</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Extended interface for XTRA support. <a href="struct_gps_xtra_interface.html#_details">More...</a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">struct </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_supl_interface.html">GpsSuplInterface</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Extended interface for SUPL support. <a href="struct_gps_supl_interface.html#_details">More...</a><br></td></tr>
+<tr><td colspan="2"><br><h2>Typedefs</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef int64_t </td><td class="memItemRight" valign="bottom"><a class="el" href="gps_8h.html#f2b0ea531a44c010f81a4abd27504c15">GpsUtcTime</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Milliseconds since January 1, 1970. <a href="#f2b0ea531a44c010f81a4abd27504c15"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef uint16_t </td><td class="memItemRight" valign="bottom"><a class="el" href="gps_8h.html#2461a6f0dd56a1f7dc94e93207a1f740">GpsPositionMode</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Requested mode for GPS operation. <a href="#2461a6f0dd56a1f7dc94e93207a1f740"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef uint16_t </td><td class="memItemRight" valign="bottom"><a class="el" href="gps_8h.html#de8fa0020d3aa1748a8e26759b768ec5">GpsStatusValue</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">GPS status event values. <a href="#de8fa0020d3aa1748a8e26759b768ec5"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef uint16_t </td><td class="memItemRight" valign="bottom"><a class="el" href="gps_8h.html#4ae31616d5e232ad7a346a2d4e723e31">GpsLocationFlags</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Flags to indicate which values are valid in a <a class="el" href="struct_gps_location.html" title="Represents a location.">GpsLocation</a>. <a href="#4ae31616d5e232ad7a346a2d4e723e31"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef uint16_t </td><td class="memItemRight" valign="bottom"><a class="el" href="gps_8h.html#93f0283aeabd20211499991a29db7377">GpsAidingData</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Flags used to specify which aiding data to delete when calling delete_aiding_data(). <a href="#93f0283aeabd20211499991a29db7377"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef void(* </td><td class="memItemRight" valign="bottom"><a class="el" href="gps_8h.html#88f19d3da70dc0e951b51091ce0631ae">gps_location_callback</a> )(<a class="el" href="struct_gps_location.html">GpsLocation</a> *location)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Callback with location information. <a href="#88f19d3da70dc0e951b51091ce0631ae"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef void(* </td><td class="memItemRight" valign="bottom"><a class="el" href="gps_8h.html#1d9ef60ab0b91f7c106867a6aa1e4412">gps_status_callback</a> )(<a class="el" href="struct_gps_status.html">GpsStatus</a> *status)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Callback with status information. <a href="#1d9ef60ab0b91f7c106867a6aa1e4412"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef void(* </td><td class="memItemRight" valign="bottom"><a class="el" href="gps_8h.html#67274e784834c6c2547f4b5344fc4ea9">gps_sv_status_callback</a> )(<a class="el" href="struct_gps_sv_status.html">GpsSvStatus</a> *sv_info)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Callback with SV status information. <a href="#67274e784834c6c2547f4b5344fc4ea9"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef void(* </td><td class="memItemRight" valign="bottom"><a class="el" href="gps_8h.html#08fcfb3f85c2ac3008c9c73cf9136515">gps_xtra_download_request</a> )()</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Callback to request the client to download XTRA data. <a href="#08fcfb3f85c2ac3008c9c73cf9136515"></a><br></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">const <a class="el" href="struct_gps_interface.html">GpsInterface</a> * </td><td class="memItemRight" valign="bottom"><a class="el" href="gps_8h.html#6d15bb02f1f91dd760e3e172bd7711a1">gps_get_hardware_interface</a> ()</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the hardware GPS interface. <a href="#6d15bb02f1f91dd760e3e172bd7711a1"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">const <a class="el" href="struct_gps_interface.html">GpsInterface</a> * </td><td class="memItemRight" valign="bottom"><a class="el" href="gps_8h.html#f73f4a220fb97545e81d82fbff54b47e">gps_get_qemu_interface</a> ()</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the qemu emulated GPS interface. <a href="#f73f4a220fb97545e81d82fbff54b47e"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">const <a class="el" href="struct_gps_interface.html">GpsInterface</a> * </td><td class="memItemRight" valign="bottom"><a class="el" href="gps_8h.html#b582931ddf4bafa2cc5044963be66987">gps_get_interface</a> ()</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the default GPS interface. <a href="#b582931ddf4bafa2cc5044963be66987"></a><br></td></tr>
+</table>
+<hr><h2>Typedef Documentation</h2>
+<a class="anchor" name="88f19d3da70dc0e951b51091ce0631ae"></a><!-- doxytag: member="gps.h::gps_location_callback" ref="88f19d3da70dc0e951b51091ce0631ae" args=")(GpsLocation *location)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef void(* <a class="el" href="gps_8h.html#88f19d3da70dc0e951b51091ce0631ae">gps_location_callback</a>)(<a class="el" href="struct_gps_location.html">GpsLocation</a> *location) </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Callback with location information.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00166">166</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="1d9ef60ab0b91f7c106867a6aa1e4412"></a><!-- doxytag: member="gps.h::gps_status_callback" ref="1d9ef60ab0b91f7c106867a6aa1e4412" args=")(GpsStatus *status)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef void(* <a class="el" href="gps_8h.html#1d9ef60ab0b91f7c106867a6aa1e4412">gps_status_callback</a>)(<a class="el" href="struct_gps_status.html">GpsStatus</a> *status) </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Callback with status information.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00169">169</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="67274e784834c6c2547f4b5344fc4ea9"></a><!-- doxytag: member="gps.h::gps_sv_status_callback" ref="67274e784834c6c2547f4b5344fc4ea9" args=")(GpsSvStatus *sv_info)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef void(* <a class="el" href="gps_8h.html#67274e784834c6c2547f4b5344fc4ea9">gps_sv_status_callback</a>)(<a class="el" href="struct_gps_sv_status.html">GpsSvStatus</a> *sv_info) </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Callback with SV status information.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00172">172</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="08fcfb3f85c2ac3008c9c73cf9136515"></a><!-- doxytag: member="gps.h::gps_xtra_download_request" ref="08fcfb3f85c2ac3008c9c73cf9136515" args=")()" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef void(* <a class="el" href="gps_8h.html#08fcfb3f85c2ac3008c9c73cf9136515">gps_xtra_download_request</a>)() </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Callback to request the client to download XTRA data.
+<p>
+The client should download XTRA data and inject it by calling inject_xtra_data().
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00226">226</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="93f0283aeabd20211499991a29db7377"></a><!-- doxytag: member="gps.h::GpsAidingData" ref="93f0283aeabd20211499991a29db7377" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef uint16_t <a class="el" href="gps_8h.html#93f0283aeabd20211499991a29db7377">GpsAidingData</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Flags used to specify which aiding data to delete when calling delete_aiding_data().
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00075">75</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="4ae31616d5e232ad7a346a2d4e723e31"></a><!-- doxytag: member="gps.h::GpsLocationFlags" ref="4ae31616d5e232ad7a346a2d4e723e31" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef uint16_t <a class="el" href="gps_8h.html#4ae31616d5e232ad7a346a2d4e723e31">GpsLocationFlags</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Flags to indicate which values are valid in a <a class="el" href="struct_gps_location.html" title="Represents a location.">GpsLocation</a>.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00059">59</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="2461a6f0dd56a1f7dc94e93207a1f740"></a><!-- doxytag: member="gps.h::GpsPositionMode" ref="2461a6f0dd56a1f7dc94e93207a1f740" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef uint16_t <a class="el" href="gps_8h.html#2461a6f0dd56a1f7dc94e93207a1f740">GpsPositionMode</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Requested mode for GPS operation.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00033">33</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="de8fa0020d3aa1748a8e26759b768ec5"></a><!-- doxytag: member="gps.h::GpsStatusValue" ref="de8fa0020d3aa1748a8e26759b768ec5" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef uint16_t <a class="el" href="gps_8h.html#de8fa0020d3aa1748a8e26759b768ec5">GpsStatusValue</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+GPS status event values.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00044">44</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="f2b0ea531a44c010f81a4abd27504c15"></a><!-- doxytag: member="gps.h::GpsUtcTime" ref="f2b0ea531a44c010f81a4abd27504c15" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef int64_t <a class="el" href="gps_8h.html#f2b0ea531a44c010f81a4abd27504c15">GpsUtcTime</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Milliseconds since January 1, 1970.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00027">27</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<hr><h2>Function Documentation</h2>
+<a class="anchor" name="6d15bb02f1f91dd760e3e172bd7711a1"></a><!-- doxytag: member="gps.h::gps_get_hardware_interface" ref="6d15bb02f1f91dd760e3e172bd7711a1" args="()" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">const <a class="el" href="struct_gps_interface.html">GpsInterface</a>* gps_get_hardware_interface </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Returns the hardware GPS interface.
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="b582931ddf4bafa2cc5044963be66987"></a><!-- doxytag: member="gps.h::gps_get_interface" ref="b582931ddf4bafa2cc5044963be66987" args="()" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">const <a class="el" href="struct_gps_interface.html">GpsInterface</a>* gps_get_interface </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Returns the default GPS interface.
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="f73f4a220fb97545e81d82fbff54b47e"></a><!-- doxytag: member="gps.h::gps_get_qemu_interface" ref="f73f4a220fb97545e81d82fbff54b47e" args="()" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">const <a class="el" href="struct_gps_interface.html">GpsInterface</a>* gps_get_qemu_interface </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Returns the qemu emulated GPS interface.
+<p>
+
+</div>
+</div><p>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/group__memory.html b/pdk/docs/group__memory.html
new file mode 100755
index 0000000..44d0782
--- /dev/null
+++ b/pdk/docs/group__memory.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+<h1>Porividng Heap Memory<br>
+<small>
+[<a class="el" href="group__networking.html">Neworking Support</a>]</small>
+</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+</table>
+This is the text in the "Providing Heap Memory" subgroup </div>
+</body>
+</html>
diff --git a/pdk/docs/group__networking.html b/pdk/docs/group__networking.html
new file mode 100755
index 0000000..6a8e1b8
--- /dev/null
+++ b/pdk/docs/group__networking.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+<h1>Neworking Support</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Modules</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__memory.html">Porividng Heap Memory</a></td></tr>
+
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+This is a text for the Networking Support Group </div>
+</body>
+</html>
diff --git a/pdk/docs/groups_8dox.html b/pdk/docs/groups_8dox.html
new file mode 100755
index 0000000..fe63ada
--- /dev/null
+++ b/pdk/docs/groups_8dox.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li class="current"><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+<h1>groups.dox File Reference</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/index.html b/pdk/docs/index.html
index 834db8f..6eac80b 100755
--- a/pdk/docs/index.html
+++ b/pdk/docs/index.html
@@ -7,6 +7,18 @@
<script src="http://code.google.com/js/jquery.js" type="text/javascript"></script>
<script type="text/javascript">var _tocPath_ = 'http://code.google.com/android/_toc.ezt';</script>
<script src="http://code.google.com/js/codesite.pack.01312008.js" type="text/javascript"></script>
+<script language="JavaScript">
+function resizeHeight() {
+ if(document.getElementById && !(document.all)) {
+ height= document.getElementById('doxygen').contentDocument.body.scrollHeight + 20;
+ document.getElementById('doxygen').style.height = height;
+ }
+ else if(document.all) {
+ height= document.frames('doxygen').document.body.scrollHeight + 20;
+ document.all.doxygen.style.height = height;
+ }
+}
+</script>
<link href="http://code.google.com/css/codesite.pack.01312008.css" type="text/css" rel="stylesheet">
</link>
@@ -33,6 +45,7 @@
<div id="skipto"> </div>
<div id="langpref">
<!--<a class="dropdown" href="/">English</a> <span>|</span> <a href="/more/">Site Directory</a> -->
+
</div>
<div id="gc-header">
<div id="logo"><a href="http://code.google.com/android/index.html"><img src="http://code.google.com/android/images/logo_android.gif" alt="Android"/></a></div>
@@ -51,6 +64,7 @@
}
</style>
</noscript>
+
<div id="searchForm2" class="searchForm2" style="display:none">
<form id="searchbox_001456098540849067467:6whlsytkdqg" action="http://www.google.com/cse">
<input type="hidden" name="cx" value="001456098540849067467:6whlsytkdqg" />
@@ -59,6 +73,7 @@
<input type="submit" name="sa" value="Search" title="Search"/>
<br/>
<div class="greytext">e.g. "ajax apis" or "open source"</div>
+
</form>
</div>
<!-- end searchForm2 -->
@@ -71,15 +86,18 @@
<div id="codesiteContent">
<a name="gc-topnav-anchor"></a>
<div id="gc-topnav">
+
<h1>Android Platform Development Kit</h1>
<ul class="gc-topnav-tabs">
<li id="sdk_link"> <a href="http://code.google.com/android/index.html" title="Android Software Development Kit">SDK</a> </li>
<li id="docs_link"> <a href="index.html" title="Official Android documentation">Docs</a> </li>
<li id="faq_link"> <a href="http://code.google.com/android/kb/index.html" title="Answers to frequently asked questions about Android">FAQ</a> </li>
+
<li> <a href="http://android-developers.blogspot.com/" title="Official Android blog">Blog</a> </li>
<li> <a href="http://code.google.com/android/groups.html" title="Android developer forum">Group</a> </li>
<li> <a href="http://code.google.com/android/terms.html" title="Android terms of service">Terms</a> </li>
- <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20index.html%20v0.3%20-%209%20June%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+ <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20index.html%20v0.6%20-%2025%20November%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+
</ul>
</div>
<!-- end gc-topnav -->
@@ -91,19 +109,18 @@
<h1><a href="index.html">Documentation</a></h1>
<ul>
<li> <strong>Introduction</strong>
+
<ul>
<li><a href="system_requirements.html">Device Requirements</a></li>
</ul>
</li>
<li> <strong>Dev Environment Setup</strong>
<ul>
- <li><a href="source_setup_guide.html">Host System Setup</a></li>
- <li><a href="getting_source_code.html">Getting Source Code</a></li>
- <li> <a href="intro_source_code.html">Source Code Overview</a></li>
<li><a href="build_system.html">Build System</a></li>
</ul>
</li>
<li> <strong>Basic Bring up</strong>
+
<ul>
<li><a href="build_new_device.html">Building New Device</a></li>
<li><a href="bring_up.html">Bring up</a></li>
@@ -111,26 +128,39 @@
<li><a href="display_drivers.html">Display Drivers</a></li>
</ul>
</li>
+
<li> <strong>Multimedia</strong>
<ul>
- <li><a href="audio_sub_system.html">Audio Subsystem</a></li>
+ <li><a href="audio_sub_system.html">Audio</a></li>
+ <li><a href="camera.html">Camera</a></li>
</ul>
</li>
<li> <strong>Power Management</strong>
+
<ul>
<li><a href="power_management.html">Power Management</a></li>
</ul>
</li>
+
+ <li> <strong>Networking</strong>
+ <ul>
+ <li><a href="wifi.html">Wi-Fi</a></li>
+ <li><a href="gps.html">GPS</a></li>
+ <li><a href="bluetooth.html">Bluetooth</a></li>
+ </ul>
+ </li>
+
<li> <strong>Telephony</strong>
<ul>
<li><a href="telephony.html">Radio Interface Layer</a></li>
+
</ul>
</li>
<li> <strong>Testing</strong>
<ul>
- <li><a href="instrumentation_framework.html">Instrumentation Framework</a></li>
<li><a href="instrumentation_testing.html">Instrumentation Testing</a></li>
</ul>
+
</li>
</ul>
</li>
@@ -212,7 +242,7 @@
pageTracker._trackPageview();
} catch(e) {}
</script>
-<div id="jd-build-id"> v0.3 - 9 June 2008</div>
+<div id="jd-build-id"> v0.6 - 25 November 2008</div>
</div></div></div></body>
</html>
diff --git a/pdk/docs/instrumentation_testing.html b/pdk/docs/instrumentation_testing.html
index 7e58ce4..bac3ca8 100755
--- a/pdk/docs/instrumentation_testing.html
+++ b/pdk/docs/instrumentation_testing.html
@@ -2,11 +2,23 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
-<title>Android - Instrumentation Testing</title>
+<title>Android - Porting Guide</title>
<script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=internal-codesite" type="text/javascript"></script>
<script src="http://code.google.com/js/jquery.js" type="text/javascript"></script>
<script type="text/javascript">var _tocPath_ = 'http://code.google.com/android/_toc.ezt';</script>
<script src="http://code.google.com/js/codesite.pack.01312008.js" type="text/javascript"></script>
+<script language="JavaScript">
+function resizeHeight() {
+ if(document.getElementById && !(document.all)) {
+ height= document.getElementById('doxygen').contentDocument.body.scrollHeight + 20;
+ document.getElementById('doxygen').style.height = height;
+ }
+ else if(document.all) {
+ height= document.frames('doxygen').document.body.scrollHeight + 20;
+ document.all.doxygen.style.height = height;
+ }
+}
+</script>
<link href="http://code.google.com/css/codesite.pack.01312008.css" type="text/css" rel="stylesheet">
</link>
@@ -33,6 +45,7 @@
<div id="skipto"> </div>
<div id="langpref">
<!--<a class="dropdown" href="/">English</a> <span>|</span> <a href="/more/">Site Directory</a> -->
+
</div>
<div id="gc-header">
<div id="logo"><a href="http://code.google.com/android/index.html"><img src="http://code.google.com/android/images/logo_android.gif" alt="Android"/></a></div>
@@ -51,6 +64,7 @@
}
</style>
</noscript>
+
<div id="searchForm2" class="searchForm2" style="display:none">
<form id="searchbox_001456098540849067467:6whlsytkdqg" action="http://www.google.com/cse">
<input type="hidden" name="cx" value="001456098540849067467:6whlsytkdqg" />
@@ -59,6 +73,7 @@
<input type="submit" name="sa" value="Search" title="Search"/>
<br/>
<div class="greytext">e.g. "ajax apis" or "open source"</div>
+
</form>
</div>
<!-- end searchForm2 -->
@@ -71,15 +86,18 @@
<div id="codesiteContent">
<a name="gc-topnav-anchor"></a>
<div id="gc-topnav">
+
<h1>Android Platform Development Kit</h1>
<ul class="gc-topnav-tabs">
<li id="sdk_link"> <a href="http://code.google.com/android/index.html" title="Android Software Development Kit">SDK</a> </li>
<li id="docs_link"> <a href="index.html" title="Official Android documentation">Docs</a> </li>
<li id="faq_link"> <a href="http://code.google.com/android/kb/index.html" title="Answers to frequently asked questions about Android">FAQ</a> </li>
+
<li> <a href="http://android-developers.blogspot.com/" title="Official Android blog">Blog</a> </li>
<li> <a href="http://code.google.com/android/groups.html" title="Android developer forum">Group</a> </li>
<li> <a href="http://code.google.com/android/terms.html" title="Android terms of service">Terms</a> </li>
- <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20instrumentation_testing.html%20v0.3%20-%209%20June%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+ <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20instrumentation_framework.html%20v0.6%20-%2025%20November%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+
</ul>
</div>
<!-- end gc-topnav -->
@@ -91,19 +109,18 @@
<h1><a href="index.html">Documentation</a></h1>
<ul>
<li> <strong>Introduction</strong>
+
<ul>
<li><a href="system_requirements.html">Device Requirements</a></li>
</ul>
</li>
<li> <strong>Dev Environment Setup</strong>
<ul>
- <li><a href="source_setup_guide.html">Host System Setup</a></li>
- <li><a href="getting_source_code.html">Getting Source Code</a></li>
- <li> <a href="intro_source_code.html">Source Code Overview</a></li>
<li><a href="build_system.html">Build System</a></li>
</ul>
</li>
<li> <strong>Basic Bring up</strong>
+
<ul>
<li><a href="build_new_device.html">Building New Device</a></li>
<li><a href="bring_up.html">Bring up</a></li>
@@ -111,26 +128,39 @@
<li><a href="display_drivers.html">Display Drivers</a></li>
</ul>
</li>
+
<li> <strong>Multimedia</strong>
<ul>
- <li><a href="audio_sub_system.html">Audio Subsystem</a></li>
+ <li><a href="audio_sub_system.html">Audio</a></li>
+ <li><a href="camera.html">Camera</a></li>
</ul>
</li>
<li> <strong>Power Management</strong>
+
<ul>
<li><a href="power_management.html">Power Management</a></li>
</ul>
</li>
+
+ <li> <strong>Networking</strong>
+ <ul>
+ <li><a href="wifi.html">Wi-Fi</a></li>
+ <li><a href="gps.html">GPS</a></li>
+ <li><a href="bluetooth.html">Bluetooth</a></li>
+ </ul>
+ </li>
+
<li> <strong>Telephony</strong>
<ul>
<li><a href="telephony.html">Radio Interface Layer</a></li>
+
</ul>
</li>
<li> <strong>Testing</strong>
<ul>
- <li><a href="instrumentation_framework.html">Instrumentation Framework</a></li>
<li><a href="instrumentation_testing.html">Instrumentation Testing</a></li>
</ul>
+
</li>
</ul>
</li>
@@ -142,32 +172,58 @@
<div class="jd-descr">
-<a name="androidTitleInstrumentationTesting"></a><h1>Instrumentation Testing</h1>
+<a name="androidTitleInstrumentationFramework"></a><h1>Instrumentation Testing</h1>
<a name="toc"/>
<div style="padding:10px">
-<a href="#androidInstrumentationTestingIntro">Introduction</a><br/>
+<a href="#androidInstrumentationFrameworkIntro">Introduction</a><br/>
+<a href="#androidInstrumentationTestingFramework">Instrumentation Framework</a><br/><div style="padding-left:40px">
+
<a href="#androidInstrumentationTestingClasses">Classes</a><br/>
-<a href="#androidInstrumentationTestingRunning">Running Tests</a><br/><div style="padding-left:40px">
+<a href="#androidInstrumentationFrameworkamCommand">Understanding the am Command</a><br/></div>
+<a href="#androidInstrumentationFrameworkPlatform">Platform Test Suites</a><br/><div style="padding-left:40px">
-<a href="#androidInstrumentationTestingRunningAll">All Tests</a><br/>
+<a href="#androidTestingPlatformFramework">Framework Tests</a><br/>
+<a href="#androidTestingPlatformCoreLibrary">Core Library</a><br/></div>
+<a href="#androidInstrumentationFrameworkWritingRunning">Running Tests</a><br/><div style="padding-left:40px">
+
+<a href="#androidInstrumentationTestingRunningAll">All Tests with Default TestRunner behavior</a><br/>
+<a href="#androidTestingTestSinglePakcage">Running all Tests Under Single Package</a><br/>
+<a href="#androidTestingSingleTestSuite">Running a Single Test Suite</a><br/>
<a href="#androidInstrumentationTestingRunningSingleTestCase">A Single Test Case</a><br/>
-<a href="#androidInstrumentationTestingRunningSingleTest">A Single Test</a><br/></div>
-<a href="#androidInstrumentationTestingCreating">Creating Tests</a><br/><div style="padding-left:40px">
+<a href="#androidInstrumentationTestingRunningSingleTest">A Single Test</a><br/>
+<a href="#androidTestingDebugging">Attaching a debugger to your test</a><br/></div>
+<a href="#androidInstrumentationTestingCreating">Writing Tests</a><br/><div style="padding-left:40px">
+<a href="#androidTestingLocationFiles">Location of Files</a><br/>
+<a href="#androidTestingContentMakefile">Contents of makefile</a><br/>
+<a href="#androidTestingContentManifest">Content of Manifest</a><br/>
<a href="#androidInstrumentationTestingCreatingTestRunner">New Instrumentation TestRunner</a><br/>
-<a href="#androidInstrumentationTestingCreatingTestCase">New InstrumentationTestCase</a><br/></div>
-<a href="#androidInstrumentationAliases">Aliases for Running Framework Instrumentation Tests</a><br/></div></font></div>
+<a href="#androidInstrumentationTestingCreatingTestCase">New InstrumentationTestCase</a><br/>
+<a href="#androidInstrumentationFrameworkTestCase">Exploring a Test Case</a><br/>
+<a href="#androidTestingKindsofTests">Deciding Kinds of Tests to Write</a><br/></div>
+<a href="#androidInstrumentationFrameworkTroubleshooting">Troubleshooting</a><br/></div></font></div>
-<a name="androidInstrumentationTestingIntro"></a><h2>Introduction</h2>
+<a name="androidInstrumentationFrameworkIntro"></a><h2>Introduction</h2>
-<p>Sometimes you may want to manually interact with your applications to verify that a particular feature or behavior is working properly; why not automate this verification with a JUnit TestCase that can instrument applications?</p>
-<p>Instrumentation testing allows you to verify a particular feature or behavior with an automated JUnit TestCase. You can launch activities and providers within an application, send key events, and make assertions about various UI elements.</p>
+<p>This document describes how to use the Instrumentation Framework to write test cases. Instrumentation testing allows you to verify a particular feature or behavior with an automated JUnit TestCase. You can launch activities and providers within an application, send key events, and make assertions about various UI elements. </p>
+<p>You should have a working knowledge of the following:</p>
+<ul>
+ <li> Android Application Framework</li>
+ <li> Using <code>adb</code>, <code>am</code> and various logging functionality </li>
+ <li> A brief understanding of the application of interest, that is, the names of the classes which handle the intents etc. </li>
+ <li> JUnit testing.</li>
+</ul>
+<p> Each Android application runs in its own process. Instrumentation kills the application process and restarts the process with Instrumentation. Instrumentation gives a handle to the application context used to poke around the application to validate test assertions, allowing you to write test cases to test applications at a much lower level than UI screen shot tests. Note that Instrumentation cannot catch UI bugs. </p>
-<a name="androidInstrumentationTestingClasses"></a><h2>Classes</h2>
+<a name="androidInstrumentationTestingFramework"></a><h2>Instrumentation Framework</h2>
+
+
+
+<a name="androidInstrumentationTestingClasses"></a><h3>Classes</h3>
<p> The following classes help glue together <code>Instrumentation</code> with JUnit testing. </p>
<table>
@@ -177,8 +233,7 @@
<tr>
<td valign="top"><code>InstrumentationTestCase</code></td>
<td valign="top">
- <p>This extends the standard JUnit <code>TestCase</code> and offers access to an <code>Instrumentation</code> class. Write tests inside your instrumentation class any way you see fit. For example, your test might launch activities and send key events. For this to work properly, the instrumentation needs to be injected into the test case.</p>
- </td>
+ <p>This extends the standard JUnit <code>TestCase</code> and offers access to an <code>Instrumentation</code> class. Write tests inside your instrumentation class any way you see fit. For example, your test might launch activities and send key events. For this to work properly, the instrumentation needs to be injected into the test case.</p> </td>
</tr>
<tr>
<td valign="top"><code>InstrumentationTestRunner</code></td>
@@ -200,6 +255,10 @@
<td valign="top"><p>This class can be used to write tests for a specific activity. An activity is launched in its <code>setUp()</code> method and finished with <code>tearDown</code>. If you write a test case that extends <code>ActivityTestCase</code>, you can write tests that access the activity using <code>getActivity()</code> and assume it has been set up properly.</p></td>
</tr>
<tr>
+ <td valign="top"><code>ServiceTestCase</code></td>
+ <td valign="top">This test case provides a framework in which you can test Service classes in a controlled environment. It provides basic support for the lifecycle of a Service, and hooks by which you can inject various dependencies and control the environment in which your Service is tested.</td>
+ </tr>
+ <tr>
<td valign="top"><code>SingleLaunchActivityTestCase</code></td>
<td valign="top">This class is similar to <code>ActivityTestCase</code> except that the activity is launched once per class instead of every time the test case calls setup. </td>
</tr>
@@ -210,8 +269,52 @@
</table>
-<a name="androidInstrumentationTestingRunning"></a><h2>Running Tests</h2>
+<a name="androidInstrumentationFrameworkamCommand"></a><h3>Understanding the am Command</h3>
+<p>The am command is a command-line interface to the ActivityManager (see <a href="http://code.google.com/android/reference/android/app/ActivityManager.html">http://code.google.com/android/reference/android/app/ActivityManager.html</a> for details). <code>am</code> is used to start and instrument activities using the adb shell command, as shown in the snippet below:</p>
+<pre class="prettify">
+> adb shell am
+usage: am [start|instrument]
+ am start [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]
+ [-c <CATEGORY> [-c <CATEGORY>] ...]
+ [-e <EXTRA_KEY> <EXTRA_VALUE> [-e <EXTRA_KEY> <EXTRA_VALUE> ...]
+ [-n <COMPONENT>] [-D] [<URI>]
+ am instrument [-e <ARG_NAME> <ARG_VALUE>] [-p <PROF_FILE>]
+ [-w] <COMPONENT>
+For example, to start the Contacts application you can use
+> adb shell am start -n com.google.android.contacts/.ContactsActivity
+</pre>
+
+
+<a name="androidInstrumentationFrameworkPlatform"></a><h2>Platform Test Suites</h2>
+
+<p>This section provides an overview for various unit and functional test cases that can be executed through the instrumentation framework.</p>
+
+
+<a name="androidTestingPlatformFramework"></a><h3>Framework Tests</h3>
+
+<p>Framework test cases test the Android application framework or specific Android application functionality that requires an Android runtime context. These tests can be found in <code>//device/tests</code> and <code>//device/apps/AndroidTests</code>.</p>
+
+
+<a name="androidTestingPlatformCoreLibrary"></a><h3>Core Library</h3>
+
+<p>Core library test cases test the Android library functionality that does not require an Android runtime context. These tests are split into Android library (android.* package space) tests at <code>//device/java/tests</code> and Java library (java.*, javax.*, etc. packages) tests at <code>//device/dalvik/libcore/.../tests</code>.</p>
+
+
+<a name="androidInstrumentationFrameworkWritingRunning"></a><h2>Running Tests</h2>
+
+<p>Each instrumentation test case is similar to an Android application with the distinction that it starts another application. For example, have a look in the <code>tests/Contacts</code> directory. </p>
+<ul>
+ <li> There should be a Makefile and an Android Manifest file. </li>
+ <li> Tests are located in <code>tests/Contacts/src/com/google/android/contactstests</code>. </li>
+ <li> The Instrumentation Test Runner is located at <code>tests/Contacts/src/com/google/android/contactstests/functional/ContactsInstrumentationTestRunner.java</code>.</li>
+</ul>
+<p>Suppose you have a makefile with <code>Contactstests</code> as the target. </p>
+<ul>
+ <li> <code>make Contactstests</code>: Compiles the test cases. </li>
+ <li> <code>adb install Contactstests.apk</code>: Installs the apk on the device. </li>
+ <li> Use the adb shell <code>am</code> command to run them. </li>
+</ul>
<p> To run your tests, use the <code>am instrument</code> command with your <code>InstrumentationTestRunner</code> as its argument. Results are printed as a result of the instrumentation. For example, the following snippet displays the output after running the framework tests with one test failing (note the unusual syntax caused by how instrumentations are run via <code>am</code>):</p>
<pre class="prettify">
$ adb shell am instrument -w com.google.android.frameworktest/.tests.FrameworkInstrumentationTestRunner
@@ -236,33 +339,185 @@
</pre>
-<a name="androidInstrumentationTestingRunningAll"></a><h3>All Tests</h3>
+<a name="androidInstrumentationTestingRunningAll"></a><h3>All Tests with Default TestRunner behavior</h3>
-<pre class="prettify">
-$ adb shell am instrument -w MyInstrumentationTestRunner
+<p>If no class or package is passed in to run, InstrumentationTestRunner will automatically find and run all tests under the package of the test application (as defined by the <code>android:targetPackage</code> attribute of the instrumentation defined in its manifest file).
+</p>
+<pre>
+$ adb shell am instrument -w \
+ com.android.samples.tests/android.test.InstrumentationTestRunner
+
+INSTRUMENTATION_RESULT: Test results for InstrumentationTestRunner=..........
+Time: 2.317
+
+OK (10 tests)
+
+
+INSTRUMENTATION_CODE: -1
</pre>
+<a name="androidTestingTestSinglePakcage"></a><h3>Running all Tests Under Single Package</h3>
+
+<p>If you have many tests under one package, use the <code>-e package <packagename></code> option to run all tests under that package without having to manually create a test suite.</p>
+<pre>
+$ adb shell am instrument -w \
+ -e package com.android.samples.view \
+ com.android.samples.tests/android.test.InstrumentationTestRunner
+INSTRUMENTATION_RESULT: Test results for InstrumentationTestRunner=........
+Time: 1.587
+
+OK (8 tests)
+</pre>
+
+
+<a name="androidTestingSingleTestSuite"></a><h3>Running a Single Test Suite</h3>
+
+<p>If you prefer to explicitly state which tests comprise all of your tests, you can define a test suite and run that directly. By convention, all test packages in your system should have at least one suite called <code>AllTests</code> (see <code>AllTests.java</code>). To run all of the tests using the <code>AllTests</code> suite for the api demos test app:</p>
+
+<pre>
+$ adb shell am instrument -w \
+ -e class com.android.samples.AllTests \
+ com.android.samples.tests/android.test.InstrumentationTestRunner
+
+INSTRUMENTATION_RESULT: Test results for AllTests=..........
+Time: 2.286
+
+OK (10 tests)
+
+
+INSTRUMENTATION_CODE: -1
+</pre>
+
+
<a name="androidInstrumentationTestingRunningSingleTestCase"></a><h3>A Single Test Case</h3>
-<pre class="prettify">
-$ adb shell am instrument \
- -e class MyInstrumentationTestCase \
- -w MyInstrumentationTestRunner
-</pre>
+<pre>
+$ adb shell am instrument -w \
+ -e class com.android.samples.view.Focus2ActivityTest \
+ com.android.samples.tests/android.test.InstrumentationTestRunner
+
+INSTRUMENTATION_RESULT: Test results for Focus2ActivityTest=....
+Time: 1.359
+
+OK (4 tests)
+
+
+INSTRUMENTATION_CODE: -1
+</pre>
<a name="androidInstrumentationTestingRunningSingleTest"></a><h3>A Single Test</h3>
-<pre class="prettify">
-$ adb shell am instrument \
- -e class MyInstrumentationTestCase#myTestMethod \
- -w MyInstrumentationTestRunner
+<pre>
+$ adb shell am instrument -w \
+ -e class com.android.samples.view.Focus2ActivityTest#testGoingLeftFromRightButtonGoesToCenter \
+ com.android.samples.tests/android.test.InstrumentationTestRunner
+
+INSTRUMENTATION_RESULT: Test results for Focus2ActivityTest=.
+Time: 0.51
+
+OK (1 test)
+
+
+INSTRUMENTATION_CODE: -1
+</pre>
+
+
+<a name="androidTestingDebugging"></a><h3>Attaching a debugger to your test</h3>
+
+<p>In order to debug your test code, instruct the controller to stop and wait for the debugger by adding <code>-e debug true</code> to your
+command line. This causes the test runner to stop and wait for the debugger just before calling your <code>setUp()</code> method. For example,</p>
+
+<pre>
+$ adb shell am instrument -w \
+ -e debug true \
+ com.android.samples.tests/android.test.InstrumentationTestRunner
+</pre>
+
+
+<a name="androidInstrumentationTestingCreating"></a><h2>Writing Tests</h2>
+
+<p>When writing tests, refer to the ApiDemos tests as models (located at <code>//device/samples/ApiDemos</code>). This section provides an overview of the test structure with ApiDemos.</p>
+
+
+<a name="androidTestingLocationFiles"></a><h3>Location of Files</h3>
+
+<p>Test packages should use the following structure and include <code>Android.mk</code>, <code>AndroidManifest.xml</code>, <code>AllTests.java</code>, and a src directory that mirrors the src directory of the tested application.</p>
+<p>Files are located within a <code>tests</code> directory found in the root directory:</p>
+<pre>
+$ find samples/ApiDemos/tests
+samples/ApiDemos/tests
+samples/ApiDemos/tests/Android.mk
+samples/ApiDemos/tests/AndroidManifest.xml
+samples/ApiDemos/tests/src
+samples/ApiDemos/tests/src/com
+samples/ApiDemos/tests/src/com/google
+samples/ApiDemos/tests/src/com/google/android
+samples/ApiDemos/tests/src/com/google/android/samples
+samples/ApiDemos/tests/src/com/google/android/samples/AllTests.java
+samples/ApiDemos/tests/src/com/google/android/samples/ApiDemosTest.java
+samples/ApiDemos/tests/src/com/google/android/samples/os
+samples/ApiDemos/tests/src/com/google/android/samples/os/MorseCodeConverterTest.java
+samples/ApiDemos/tests/src/com/google/android/samples/view
+samples/ApiDemos/tests/src/com/google/android/samples/view/Focus2ActivityTest.java
+samples/ApiDemos/tests/src/com/google/android/samples/view/Focus2AndroidTest.java
</pre>
-<a name="androidInstrumentationTestingCreating"></a><h2>Creating Tests</h2>
+<a name="androidTestingContentMakefile"></a><h3>Contents of makefile</h3>
+<p>The contents of the makefile are similar to a normal application with the addition of a <code>LOCAL_INSTRUMENTATION_FOR</code> declaration.<p />
+<pre>
+# Add appropriate copyright banner here
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Notice that we don't have to include the src files of ApiDemos because, by
+# running the tests using an instrumentation targeting ApiDemos, we
+# automatically get all of its classes loaded into our environment.
+
+LOCAL_PACKAGE_NAME := ApiDemosTests
+
+LOCAL_INSTRUMENTATION_FOR := ApiDemos
+
+include $(BUILD_PACKAGE)
+</pre>
+
+
+<a name="androidTestingContentManifest"></a><h3>Content of Manifest</h3>
+
+<p>Use the following example to create an <code>AndroidManifest.xml</code> file that declares the instrumentation. Specify that the framework supplied Instrumentation TestRunner targest the package of your application, allowing the tests that are run with the instrumentation to get access to all of the classes of your application without having to build the source into the test app. The name of the test application is typically the same as your target application with <code>.tests</code> appended. </p>
+<pre>
+# Add appropriate copyright banner here
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.samples.tests">
+
+ <uses-permission android:name="android.permission.RUN_INSTRUMENTATION" />
+
+ <!--
+ This declares that this app uses the instrumentation test runner targeting
+ the package of com.android.samples. To run the tests use the command:
+ "adb shell am instrument -w com.android.samples.tests/android.test.InstrumentationTestRunner"
+ -->
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.samples"
+ android:label="Tests for Api Demos."/>
+
+</manifest>
+</pre>
+<p> </p>
+<p>The following snippet will prefix the <code>/android.test.InstrumentationTestRunner</code> when running tests from the command line:</p>
+<pre>
+$ adb shell am instrument -w \
+ com.android.samples.tests/android.test.InstrumentationTestRunner
+</pre>
<a name="androidInstrumentationTestingCreatingTestRunner"></a><h3>New Instrumentation TestRunner</h3>
@@ -328,26 +583,106 @@
</pre>
-<a name="androidInstrumentationAliases"></a><h2>Aliases for Running Framework Instrumentation Tests</h2>
+<a name="androidInstrumentationFrameworkTestCase"></a><h3>Exploring a Test Case</h3>
+<p> The test case described in this section adds and tests a new Contact. Note that you can send intents, register intent receivers, etc. </p>
+<p><code>Instrumentation.java</code> has helper functions that send key events and strings, for example: </p>
+<ul>
+ <li><code>getInstrumentation()</code>: Returns the handle to the instrumentation </li>
+ <li><code>sendCharacterSync</code>: Sends a character. </li>
+ <li><code>sendStringSync</code>: Sends a string to an input box. </li>
+ <li><code>sendKeyDownUpSync</code>: Sends a specific keyevent. </li>
+ <li><code>sendTrackballEventSync</code>: Sends a trackball event.</li>
+</ul>
+<p> You can find the test case below at <code>device/tests/Contacts.</code></p>
<pre class="prettify">
-# compiles and installs FrameworkTests
-alias deploytests="(cd tests/FrameworkTests/ && mm) && adb install out/target/product/dream/system/app/FrameworkTest.apk"
+private void addNewContact(String name, int star, int phoneType, String number, String label,
+ String email, int emailType){
+ ContentValues values = new ContentValues();
+ Uri phoneUri = null;
+ Uri emailUri = null;
-# runs all of FrameworkTests unit tests
-alias runtests="adb shell am instrument -w com.google.android.frameworktest/.tests.FrameworkInstrumentationTestRunner"
+ values.put(Contacts.People.NAME, name);
+ values.put(Contacts.People.STARRED, star);
-# runtest TEST: runs a single unit test, for instance runtest view.VisibilityTest
-# -- for convenience, you don't have to type the com.google.android.frameworktest.tests.
-function runtest {
- adb shell am instrument -e class com.google.android.frameworktest.tests.$1 -w com.google.android.frameworktest/.tests.FrameworkInstrumentationTestRunner
+ //Add Phone Numbers
+ Uri uri = mActivity.getContentResolver().insert(Contacts.People.CONTENT_URI, values);
+ phoneUri = Uri.withAppendedPath(uri, Contacts.People.Phones.CONTENT_DIRECTORY);
+
+ values.clear();
+ values.put(Contacts.Phones.TYPE, phoneType);
+ values.put(Contacts.Phones.NUMBER, number);
+ values.put(Contacts.Phones.LABEL, label);
+ mActivity.getContentResolver().insert(phoneUri, values);
+
+ //Add Email
+ emailUri = Uri.withAppendedPath(uri, ContactMethods.CONTENT_DIRECTORY);
+
+ values.clear();
+ values.put(ContactMethods.KIND, Contacts.KIND_EMAIL);
+ values.put(ContactMethods.DATA, email);
+ values.put(ContactMethods.LABEL, "");
+ values.put(ContactMethods.TYPE, emailType);
+ mActivity.getContentResolver().insert(emailUri, values);
}
-# debugtest TEST: runs a single unit test in debug mode, for instance runtest view.VisibilityTest
-function debugtest {
- adb shell am instrument -e debug true -e class com.google.android.frameworktest.tests.$1 -w com.google.android.frameworktest/.tests.FrameworkInstrumentationTestRunner
+
+ public void testAddSaveSingleContact(){
+ int previousCount = mActivity.getListView().getCount();
+ String message;
+
+ addNewContact(INPUT_NAME_1 + "1", "5435754532", "1" + INPUT_EMAIL_1, CONFIRM_OPTION);
+
+ message = "Added 1 to initial length=" + previousCount + ", but resulted with a count=" +
+ mActivity.getListView().getCount();
+ assertEquals(message, ++previousCount, mActivity.getListView().getCount());
+
+ // Check Content; Name; Num; Starred
+ assertEquals(INPUT_NAME_1 + "1", getTextFromView(0, android.R.id.text1));
+ assertEquals("5435754532", getTextFromView(0, android.R.id.text2));
+
+ //Check email is saved
+ //cursor = returnEmailCursorAtId("1");
+ Uri uri = Uri.parse("content://contacts/people/1");
+ uri = Uri.withAppendedPath(uri, ContactMethods.CONTENT_DIRECTORY);
+ Cursor cursor = mActivity.getContentResolver().query(uri, CONTACTS_COLUMNS, null, null, null);
+ assertTrue("returnEmailCursorAtId: Moving cursor to first row has failed", cursor.first());
+
+ int dataIndex = cursor.getColumnIndexOrThrow("data");
+ assertEquals("1" + INPUT_EMAIL_1, cursor.getString(dataIndex));
+ cursor.deactivate();
}
-</pre>
+ </pre>
+
+
+<a name="androidTestingKindsofTests"></a><h3>Deciding Kinds of Tests to Write</h3>
+
+<p>Once you are bootstrapped with your test application, you can start writing tests. There are three of types of tests you may wish to write:</p>
+<p><ul>
+<li> <strong>TestCase</strong>: The standard junit test case.
+</li>
+<li> <strong>AndroidTestCase</strong>: A test case with access to a Context object that is injected for you by the instrumentation test runner.
+</li>
+<li> <strong>InstrumentationTestCase</strong>: A test case with access to an Instrumentation, which can be used to launch activities, content providers, send key events, etc.
+</li>
+</ul>
+</p>
+<p>The API Demos test suite includes examples of all three styles and can be used as a guideline for writing each type of test.</p>
+<p>There are two utility classes available for the most common uses of InstrumentationTestCase: ActivityTestCase and ProviderTestCase. See their javadoc for more information.
+</p>
+
+
+<a name="androidInstrumentationFrameworkTroubleshooting"></a><h2>Troubleshooting</h2>
+
+<p>If you run your test cases and nothing appears to happen, have a look at <code>adb logcat</code>. The following is a common problem:</p>
+<pre class="prettify">
+I/dalvikvm( 688): threadid=11: attached from native, name=Binder Thread #1
+I/dalvikvm( 688): threadid=13: attached from native, name=Binder Thread #2
+W/ActivityManager( 469): Unable to find instrumentation info for: ComponentInfo{com.google.android.browser_instrumentation/com.google.android.browser_instrumentation.BrowserWebkitLayoutInstrumentation}
+D/AndroidRuntime( 688): Shutting down VM
+E/AndroidRuntime( 688): ERROR: thread attach failed
+</pre>
+<p>It's possible that the instrumentation apk isn't installed on your device or that the package name is incorrect in the Manifest file. </p>
<p><span class="lh2"><a name="androidFooter"></a></span>
@@ -375,7 +710,7 @@
pageTracker._trackPageview();
} catch(e) {}
</script>
-<div id="jd-build-id"> v0.3 - 9 June 2008</div>
+<div id="jd-build-id"> v0.6 - 25 November 2008</div>
</div></div></div></body>
</html>
diff --git a/pdk/docs/intro_source_code.html b/pdk/docs/intro_source_code.html
index d4ab4e4..f86b568 100755
--- a/pdk/docs/intro_source_code.html
+++ b/pdk/docs/intro_source_code.html
@@ -2,11 +2,23 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
-<title>Android - Source Code Overview</title>
+<title>Android - Porting Guide</title>
<script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=internal-codesite" type="text/javascript"></script>
<script src="http://code.google.com/js/jquery.js" type="text/javascript"></script>
<script type="text/javascript">var _tocPath_ = 'http://code.google.com/android/_toc.ezt';</script>
<script src="http://code.google.com/js/codesite.pack.01312008.js" type="text/javascript"></script>
+<script language="JavaScript">
+function resizeHeight() {
+ if(document.getElementById && !(document.all)) {
+ height= document.getElementById('doxygen').contentDocument.body.scrollHeight + 20;
+ document.getElementById('doxygen').style.height = height;
+ }
+ else if(document.all) {
+ height= document.frames('doxygen').document.body.scrollHeight + 20;
+ document.all.doxygen.style.height = height;
+ }
+}
+</script>
<link href="http://code.google.com/css/codesite.pack.01312008.css" type="text/css" rel="stylesheet">
</link>
@@ -33,6 +45,7 @@
<div id="skipto"> </div>
<div id="langpref">
<!--<a class="dropdown" href="/">English</a> <span>|</span> <a href="/more/">Site Directory</a> -->
+
</div>
<div id="gc-header">
<div id="logo"><a href="http://code.google.com/android/index.html"><img src="http://code.google.com/android/images/logo_android.gif" alt="Android"/></a></div>
@@ -51,6 +64,7 @@
}
</style>
</noscript>
+
<div id="searchForm2" class="searchForm2" style="display:none">
<form id="searchbox_001456098540849067467:6whlsytkdqg" action="http://www.google.com/cse">
<input type="hidden" name="cx" value="001456098540849067467:6whlsytkdqg" />
@@ -59,6 +73,7 @@
<input type="submit" name="sa" value="Search" title="Search"/>
<br/>
<div class="greytext">e.g. "ajax apis" or "open source"</div>
+
</form>
</div>
<!-- end searchForm2 -->
@@ -71,15 +86,18 @@
<div id="codesiteContent">
<a name="gc-topnav-anchor"></a>
<div id="gc-topnav">
+
<h1>Android Platform Development Kit</h1>
<ul class="gc-topnav-tabs">
<li id="sdk_link"> <a href="http://code.google.com/android/index.html" title="Android Software Development Kit">SDK</a> </li>
<li id="docs_link"> <a href="index.html" title="Official Android documentation">Docs</a> </li>
<li id="faq_link"> <a href="http://code.google.com/android/kb/index.html" title="Answers to frequently asked questions about Android">FAQ</a> </li>
+
<li> <a href="http://android-developers.blogspot.com/" title="Official Android blog">Blog</a> </li>
<li> <a href="http://code.google.com/android/groups.html" title="Android developer forum">Group</a> </li>
<li> <a href="http://code.google.com/android/terms.html" title="Android terms of service">Terms</a> </li>
- <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20intro_source_code.html%20v0.3%20-%209%20June%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+ <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20index.html%20v0.5%20-%2025%20September%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+
</ul>
</div>
<!-- end gc-topnav -->
@@ -91,6 +109,7 @@
<h1><a href="index.html">Documentation</a></h1>
<ul>
<li> <strong>Introduction</strong>
+
<ul>
<li><a href="system_requirements.html">Device Requirements</a></li>
</ul>
@@ -98,12 +117,14 @@
<li> <strong>Dev Environment Setup</strong>
<ul>
<li><a href="source_setup_guide.html">Host System Setup</a></li>
+
<li><a href="getting_source_code.html">Getting Source Code</a></li>
<li> <a href="intro_source_code.html">Source Code Overview</a></li>
<li><a href="build_system.html">Build System</a></li>
</ul>
</li>
<li> <strong>Basic Bring up</strong>
+
<ul>
<li><a href="build_new_device.html">Building New Device</a></li>
<li><a href="bring_up.html">Bring up</a></li>
@@ -111,26 +132,39 @@
<li><a href="display_drivers.html">Display Drivers</a></li>
</ul>
</li>
+
<li> <strong>Multimedia</strong>
<ul>
<li><a href="audio_sub_system.html">Audio Subsystem</a></li>
+ <li><a href="camera.html">Camera</a></li>
</ul>
</li>
<li> <strong>Power Management</strong>
+
<ul>
<li><a href="power_management.html">Power Management</a></li>
</ul>
</li>
+
+ <li> <strong>Networking</strong>
+ <ul>
+ <li><a href="wifi.html">Wi-Fi</a></li>
+ <li><a href="gps.html">GPS</a></li>
+ <li><a href="bluetooth.html">Bluetooth</a></li>
+ </ul>
+ </li>
+
<li> <strong>Telephony</strong>
<ul>
<li><a href="telephony.html">Radio Interface Layer</a></li>
+
</ul>
</li>
<li> <strong>Testing</strong>
<ul>
- <li><a href="instrumentation_framework.html">Instrumentation Framework</a></li>
<li><a href="instrumentation_testing.html">Instrumentation Testing</a></li>
</ul>
+
</li>
</ul>
</li>
@@ -194,107 +228,107 @@
<li>apps
-: Core Android applications such as Phone, Camera, and Calendar.
+Core Android applications such as Phone, Camera, and Calendar.
</li>
<li>boot
-: Reference Android bootloader and other boot-related source code.
+Reference Android bootloader and other boot-related source code.
</li>
<li>commands
-: Common Android commands, the most important of which is the runtime command, which does much of the initialization of the system.
+Common Android commands, the most important of which is the runtime command, which does much of the initialization of the system.
</li>
<li>config
-: System-wide makefiles and linker scripts.
+System-wide makefiles and linker scripts.
</li>
<li>content
-: Standard Android ContentProvider modules.
+Standard Android ContentProvider modules.
</li>
<li>dalvik
-: Android runtime Virtual Machine (VM).
+Android runtime Virtual Machine (VM).
</li>
<li>data
-: Fonts, keymaps, sounds, timezone information, etc.
+Fonts, keymaps, sounds, timezone information, etc.
</li>
<li>docs
-: Full set of Android documentation.
+Full set of Android documentation.
</li>
<li>extlibs
-: Non-Android libraries. This directory is intended to host unmodified external code. None of the libraries included within this directory rely on Android headers or libraries.
+Non-Android libraries. This directory is intended to host unmodified external code. None of the libraries included within this directory rely on Android headers or libraries.
</li>
<li>ide
-: Tools for support of the IDE's used to write Android applications.
+Tools for support of the IDE's used to write Android applications.
</li>
<li>include
-: Android system headers for inclusion.
+Android system headers for inclusion.
</li>
<li>java
-: Android core APIs, as well as some external libraries.
+Android core APIs, as well as some external libraries.
</li>
<li>libs
-: Android-specific C++ based libraries.
+Android-specific C++ based libraries.
</li>
<li>partner
-: Project-specific source code for various proprietary components.
+Project-specific source code for various proprietary components.
</li>
<li>prebuilt
-: Prebuilt tools, like the toolchains and emulator binary.
+Prebuilt tools, like the toolchains and emulator binary.
</li>
<li>product
-: Device-specific configuration files. This directory will include a subdirectory for each new device.
+Device-specific configuration files. This directory will include a subdirectory for each new device.
</li>
<li>samples
-: Sample applications.
+Sample applications.
</li>
<li>servers
-: C++ based system servers.
+C++ based system servers.
</li>
<li>system
-: Core of the embedded Linux platform at the heart of Android. These essential bits are required for basic booting, operation, and debugging.
+Core of the embedded Linux platform at the heart of Android. These essential bits are required for basic booting, operation, and debugging.
</li>
<li>tests
-: Platform and application test cases.
+Platform and application test cases.
</li>
<li>tools
-: Tools for building and debugging Android (of particular interest for porting are "adb" and "emulator").
+Tools for building and debugging Android (of particular interest for porting are "adb" and "emulator").
</li>
@@ -338,7 +372,7 @@
pageTracker._trackPageview();
} catch(e) {}
</script>
-<div id="jd-build-id"> v0.3 - 9 June 2008</div>
+<div id="jd-build-id"> v0.5 - 25 September 2008</div>
</div></div></div></body>
</html>
diff --git a/pdk/docs/keymaps_keyboard_input.html b/pdk/docs/keymaps_keyboard_input.html
index 392369d..9a1a66a 100755
--- a/pdk/docs/keymaps_keyboard_input.html
+++ b/pdk/docs/keymaps_keyboard_input.html
@@ -2,11 +2,23 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
-<title>Android - Keympas and Keyboard Input</title>
+<title>Android - Porting Guide</title>
<script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=internal-codesite" type="text/javascript"></script>
<script src="http://code.google.com/js/jquery.js" type="text/javascript"></script>
<script type="text/javascript">var _tocPath_ = 'http://code.google.com/android/_toc.ezt';</script>
<script src="http://code.google.com/js/codesite.pack.01312008.js" type="text/javascript"></script>
+<script language="JavaScript">
+function resizeHeight() {
+ if(document.getElementById && !(document.all)) {
+ height= document.getElementById('doxygen').contentDocument.body.scrollHeight + 20;
+ document.getElementById('doxygen').style.height = height;
+ }
+ else if(document.all) {
+ height= document.frames('doxygen').document.body.scrollHeight + 20;
+ document.all.doxygen.style.height = height;
+ }
+}
+</script>
<link href="http://code.google.com/css/codesite.pack.01312008.css" type="text/css" rel="stylesheet">
</link>
@@ -33,6 +45,7 @@
<div id="skipto"> </div>
<div id="langpref">
<!--<a class="dropdown" href="/">English</a> <span>|</span> <a href="/more/">Site Directory</a> -->
+
</div>
<div id="gc-header">
<div id="logo"><a href="http://code.google.com/android/index.html"><img src="http://code.google.com/android/images/logo_android.gif" alt="Android"/></a></div>
@@ -51,6 +64,7 @@
}
</style>
</noscript>
+
<div id="searchForm2" class="searchForm2" style="display:none">
<form id="searchbox_001456098540849067467:6whlsytkdqg" action="http://www.google.com/cse">
<input type="hidden" name="cx" value="001456098540849067467:6whlsytkdqg" />
@@ -59,6 +73,7 @@
<input type="submit" name="sa" value="Search" title="Search"/>
<br/>
<div class="greytext">e.g. "ajax apis" or "open source"</div>
+
</form>
</div>
<!-- end searchForm2 -->
@@ -71,15 +86,18 @@
<div id="codesiteContent">
<a name="gc-topnav-anchor"></a>
<div id="gc-topnav">
+
<h1>Android Platform Development Kit</h1>
<ul class="gc-topnav-tabs">
<li id="sdk_link"> <a href="http://code.google.com/android/index.html" title="Android Software Development Kit">SDK</a> </li>
<li id="docs_link"> <a href="index.html" title="Official Android documentation">Docs</a> </li>
<li id="faq_link"> <a href="http://code.google.com/android/kb/index.html" title="Answers to frequently asked questions about Android">FAQ</a> </li>
+
<li> <a href="http://android-developers.blogspot.com/" title="Official Android blog">Blog</a> </li>
<li> <a href="http://code.google.com/android/groups.html" title="Android developer forum">Group</a> </li>
<li> <a href="http://code.google.com/android/terms.html" title="Android terms of service">Terms</a> </li>
- <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20eymaps_keyboard_input.html%20v0.3%20-%209%20June%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+ <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20eymaps_keyboard_input.html%20v0.6%20-%2025%20November%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+
</ul>
</div>
<!-- end gc-topnav -->
@@ -91,19 +109,18 @@
<h1><a href="index.html">Documentation</a></h1>
<ul>
<li> <strong>Introduction</strong>
+
<ul>
<li><a href="system_requirements.html">Device Requirements</a></li>
</ul>
</li>
<li> <strong>Dev Environment Setup</strong>
<ul>
- <li><a href="source_setup_guide.html">Host System Setup</a></li>
- <li><a href="getting_source_code.html">Getting Source Code</a></li>
- <li> <a href="intro_source_code.html">Source Code Overview</a></li>
<li><a href="build_system.html">Build System</a></li>
</ul>
</li>
<li> <strong>Basic Bring up</strong>
+
<ul>
<li><a href="build_new_device.html">Building New Device</a></li>
<li><a href="bring_up.html">Bring up</a></li>
@@ -111,26 +128,39 @@
<li><a href="display_drivers.html">Display Drivers</a></li>
</ul>
</li>
+
<li> <strong>Multimedia</strong>
<ul>
- <li><a href="audio_sub_system.html">Audio Subsystem</a></li>
+ <li><a href="audio_sub_system.html">Audio</a></li>
+ <li><a href="camera.html">Camera</a></li>
</ul>
</li>
<li> <strong>Power Management</strong>
+
<ul>
<li><a href="power_management.html">Power Management</a></li>
</ul>
</li>
+
+ <li> <strong>Networking</strong>
+ <ul>
+ <li><a href="wifi.html">Wi-Fi</a></li>
+ <li><a href="gps.html">GPS</a></li>
+ <li><a href="bluetooth.html">Bluetooth</a></li>
+ </ul>
+ </li>
+
<li> <strong>Telephony</strong>
<ul>
<li><a href="telephony.html">Radio Interface Layer</a></li>
+
</ul>
</li>
<li> <strong>Testing</strong>
<ul>
- <li><a href="instrumentation_framework.html">Instrumentation Framework</a></li>
<li><a href="instrumentation_testing.html">Instrumentation Testing</a></li>
</ul>
+
</li>
</ul>
</li>
@@ -235,7 +265,7 @@
<p>The following code comes from <code>android/src/device/product/generic/tuttle2.kl</code> and is an example of a complete key layout file:</p>
<pre class="prettify">
-# Copyright 2007 The Android Open Source Project
+# Copyright 2007 Google Inc.
key 2 1
key 3 2
@@ -300,7 +330,7 @@
key 50 M
key 51 COMMA
key 52 PERIOD
-key 28 ENTER
+key 28 NEWLINE
key 56 ALT_LEFT
key 42 SHIFT_LEFT
@@ -374,7 +404,7 @@
</ul>
</p>
<pre class="prettify">
-# Copyright 2007 The Android Open Source Project
+# Copyright 2007 Google Inc.
[type=QWERTY]
@@ -518,7 +548,7 @@
* of the macros is not meant to trivialize the work required, just as
* an indication of where the work needs to be done.
*
- * Copyright 2007, The Android Open Source Project
+ * Copyright 2007, Google Inc.
* Based on goldfish-events.c
*
*/
@@ -677,7 +707,7 @@
pageTracker._trackPageview();
} catch(e) {}
</script>
-<div id="jd-build-id"> v0.3 - 9 June 2008</div>
+<div id="jd-build-id"> v0.6 - 25 November 2008</div>
</div></div></div></body>
</html>
diff --git a/pdk/docs/main_8dox.html b/pdk/docs/main_8dox.html
new file mode 100755
index 0000000..b4bf177
--- /dev/null
+++ b/pdk/docs/main_8dox.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li class="current"><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+<h1>main.dox File Reference</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/modules.html b/pdk/docs/modules.html
new file mode 100755
index 0000000..ea2a07a
--- /dev/null
+++ b/pdk/docs/modules.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li class="current"><a href="modules.html"><span>Modules</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+<h1>Modules</h1>Here is a list of all modules:<ul>
+<li><a class="el" href="group__networking.html">Neworking Support</a>
+<ul>
+<li><a class="el" href="group__memory.html">Porividng Heap Memory</a>
+</ul>
+</ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/namespaceandroid.html b/pdk/docs/namespaceandroid.html
new file mode 100755
index 0000000..ee0b03f
--- /dev/null
+++ b/pdk/docs/namespaceandroid.html
@@ -0,0 +1,214 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li class="current"><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="namespaces.html"><span>Namespace List</span></a></li>
+ <li><a href="namespacemembers.html"><span>Namespace Members</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+<h1>android Namespace Reference</h1>
+<p>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Data Structures</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">class </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_out.html">AudioStreamOut</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight"><a class="el" href="classandroid_1_1_audio_stream_out.html" title="AudioStreamOut is the abstraction interface for the audio output hardware.">AudioStreamOut</a> is the abstraction interface for the audio output hardware. <a href="classandroid_1_1_audio_stream_out.html#_details">More...</a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">class </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_stream_in.html">AudioStreamIn</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight"><a class="el" href="classandroid_1_1_audio_stream_in.html" title="AudioStreamIn is the abstraction interface for the audio input hardware.">AudioStreamIn</a> is the abstraction interface for the audio input hardware. <a href="classandroid_1_1_audio_stream_in.html#_details">More...</a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">class </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_audio_hardware_interface.html">AudioHardwareInterface</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight"><a class="el" href="_audio_hardware_interface_8h.html">AudioHardwareInterface.h</a> defines the interface to the audio hardware abstraction layer. <a href="classandroid_1_1_audio_hardware_interface.html#_details">More...</a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">class </td><td class="memItemRight" valign="bottom"><a class="el" href="classandroid_1_1_camera_hardware_interface.html">CameraHardwareInterface</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight"><a class="el" href="_camera_hardware_interface_8h.html">CameraHardwareInterface.h</a> defines the interface to the camera hardware abstraction layer, used for setting and getting parameters, live previewing, and taking pictures. <a href="classandroid_1_1_camera_hardware_interface.html#_details">More...</a><br></td></tr>
+<tr><td colspan="2"><br><h2>Typedefs</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef void(* </td><td class="memItemRight" valign="bottom"><a class="el" href="namespaceandroid.html#d32b08663d42356404e2eb971e271636">preview_callback</a> )(const sp< IMemory > &mem, void *user)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Callback for startPreview(). <a href="#d32b08663d42356404e2eb971e271636"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef void(* </td><td class="memItemRight" valign="bottom"><a class="el" href="namespaceandroid.html#04c83209c2627e2d303320712ca9ee65">shutter_callback</a> )(void *user)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Callback for takePicture(). <a href="#04c83209c2627e2d303320712ca9ee65"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef void(* </td><td class="memItemRight" valign="bottom"><a class="el" href="namespaceandroid.html#a97926709e452d66360cb9b24736969e">raw_callback</a> )(const sp< IMemory > &mem, void *user)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Callback for takePicture(). <a href="#a97926709e452d66360cb9b24736969e"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef void(* </td><td class="memItemRight" valign="bottom"><a class="el" href="namespaceandroid.html#c21980d4be1e0cc458399ecf5374d473">jpeg_callback</a> )(const sp< IMemory > &mem, void *user)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Callback for takePicture(). <a href="#c21980d4be1e0cc458399ecf5374d473"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef void(* </td><td class="memItemRight" valign="bottom"><a class="el" href="namespaceandroid.html#4dca8d8b824ca9a684358133da0ec8f2">autofocus_callback</a> )(bool focused, void *user)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Callback for autoFocus(). <a href="#4dca8d8b824ca9a684358133da0ec8f2"></a><br></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="el" href="classandroid_1_1_audio_hardware_interface.html">AudioHardwareInterface</a> * </td><td class="memItemRight" valign="bottom"><a class="el" href="namespaceandroid.html#dcc80314ddffcb0981a9e9c5468662f8">createAudioHardware</a> (void)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">sp< <a class="el" href="classandroid_1_1_camera_hardware_interface.html">CameraHardwareInterface</a> > </td><td class="memItemRight" valign="bottom"><a class="el" href="namespaceandroid.html#24c243f7f9ba0d1d881be17ae06254a2">openCameraHardware</a> ()</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">factory function to instantiate a camera hardware object <a href="#24c243f7f9ba0d1d881be17ae06254a2"></a><br></td></tr>
+</table>
+<hr><h2>Typedef Documentation</h2>
+<a class="anchor" name="4dca8d8b824ca9a684358133da0ec8f2"></a><!-- doxytag: member="android::autofocus_callback" ref="4dca8d8b824ca9a684358133da0ec8f2" args=")(bool focused, void *user)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef void(* <a class="el" href="namespaceandroid.html#4dca8d8b824ca9a684358133da0ec8f2">android::autofocus_callback</a>)(bool focused, void *user) </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Callback for autoFocus().
+<p>
+
+<p>Definition at line <a class="el" href="_camera_hardware_interface_8h-source.html#l00039">39</a> of file <a class="el" href="_camera_hardware_interface_8h-source.html">CameraHardwareInterface.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="c21980d4be1e0cc458399ecf5374d473"></a><!-- doxytag: member="android::jpeg_callback" ref="c21980d4be1e0cc458399ecf5374d473" args=")(const sp< IMemory > &mem, void *user)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef void(* <a class="el" href="namespaceandroid.html#c21980d4be1e0cc458399ecf5374d473">android::jpeg_callback</a>)(const sp< IMemory > &mem, void *user) </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Callback for takePicture().
+<p>
+
+<p>Definition at line <a class="el" href="_camera_hardware_interface_8h-source.html#l00036">36</a> of file <a class="el" href="_camera_hardware_interface_8h-source.html">CameraHardwareInterface.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="d32b08663d42356404e2eb971e271636"></a><!-- doxytag: member="android::preview_callback" ref="d32b08663d42356404e2eb971e271636" args=")(const sp< IMemory > &mem, void *user)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef void(* <a class="el" href="namespaceandroid.html#d32b08663d42356404e2eb971e271636">android::preview_callback</a>)(const sp< IMemory > &mem, void *user) </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Callback for startPreview().
+<p>
+
+<p>Definition at line <a class="el" href="_camera_hardware_interface_8h-source.html#l00027">27</a> of file <a class="el" href="_camera_hardware_interface_8h-source.html">CameraHardwareInterface.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="a97926709e452d66360cb9b24736969e"></a><!-- doxytag: member="android::raw_callback" ref="a97926709e452d66360cb9b24736969e" args=")(const sp< IMemory > &mem, void *user)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef void(* <a class="el" href="namespaceandroid.html#a97926709e452d66360cb9b24736969e">android::raw_callback</a>)(const sp< IMemory > &mem, void *user) </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Callback for takePicture().
+<p>
+
+<p>Definition at line <a class="el" href="_camera_hardware_interface_8h-source.html#l00033">33</a> of file <a class="el" href="_camera_hardware_interface_8h-source.html">CameraHardwareInterface.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="04c83209c2627e2d303320712ca9ee65"></a><!-- doxytag: member="android::shutter_callback" ref="04c83209c2627e2d303320712ca9ee65" args=")(void *user)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef void(* <a class="el" href="namespaceandroid.html#04c83209c2627e2d303320712ca9ee65">android::shutter_callback</a>)(void *user) </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Callback for takePicture().
+<p>
+
+<p>Definition at line <a class="el" href="_camera_hardware_interface_8h-source.html#l00030">30</a> of file <a class="el" href="_camera_hardware_interface_8h-source.html">CameraHardwareInterface.h</a>.</p>
+
+</div>
+</div><p>
+<hr><h2>Function Documentation</h2>
+<a class="anchor" name="dcc80314ddffcb0981a9e9c5468662f8"></a><!-- doxytag: member="android::createAudioHardware" ref="dcc80314ddffcb0981a9e9c5468662f8" args="(void)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="classandroid_1_1_audio_hardware_interface.html">AudioHardwareInterface</a>* android::createAudioHardware </td>
+ <td>(</td>
+ <td class="paramtype">void </td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="24c243f7f9ba0d1d881be17ae06254a2"></a><!-- doxytag: member="android::openCameraHardware" ref="24c243f7f9ba0d1d881be17ae06254a2" args="()" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">sp<<a class="el" href="classandroid_1_1_camera_hardware_interface.html">CameraHardwareInterface</a>> android::openCameraHardware </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+factory function to instantiate a camera hardware object
+<p>
+
+</div>
+</div><p>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/namespacemembers.html b/pdk/docs/namespacemembers.html
new file mode 100755
index 0000000..9644de2
--- /dev/null
+++ b/pdk/docs/namespacemembers.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li class="current"><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="namespaces.html"><span>Namespace List</span></a></li>
+ <li class="current"><a href="namespacemembers.html"><span>Namespace Members</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li class="current"><a href="namespacemembers.html"><span>All</span></a></li>
+ <li><a href="namespacemembers_func.html"><span>Functions</span></a></li>
+ <li><a href="namespacemembers_type.html"><span>Typedefs</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+Here is a list of all namespace members with links to the namespace documentation for each member:
+<p>
+<ul>
+<li>autofocus_callback
+: <a class="el" href="namespaceandroid.html#4dca8d8b824ca9a684358133da0ec8f2">android</a>
+<li>createAudioHardware()
+: <a class="el" href="namespaceandroid.html#dcc80314ddffcb0981a9e9c5468662f8">android</a>
+<li>jpeg_callback
+: <a class="el" href="namespaceandroid.html#c21980d4be1e0cc458399ecf5374d473">android</a>
+<li>openCameraHardware()
+: <a class="el" href="namespaceandroid.html#24c243f7f9ba0d1d881be17ae06254a2">android</a>
+<li>preview_callback
+: <a class="el" href="namespaceandroid.html#d32b08663d42356404e2eb971e271636">android</a>
+<li>raw_callback
+: <a class="el" href="namespaceandroid.html#a97926709e452d66360cb9b24736969e">android</a>
+<li>shutter_callback
+: <a class="el" href="namespaceandroid.html#04c83209c2627e2d303320712ca9ee65">android</a>
+</ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/namespacemembers_func.html b/pdk/docs/namespacemembers_func.html
new file mode 100755
index 0000000..eaa31a5
--- /dev/null
+++ b/pdk/docs/namespacemembers_func.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li class="current"><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="namespaces.html"><span>Namespace List</span></a></li>
+ <li class="current"><a href="namespacemembers.html"><span>Namespace Members</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="namespacemembers.html"><span>All</span></a></li>
+ <li class="current"><a href="namespacemembers_func.html"><span>Functions</span></a></li>
+ <li><a href="namespacemembers_type.html"><span>Typedefs</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+
+<p>
+<ul>
+<li>createAudioHardware()
+: <a class="el" href="namespaceandroid.html#dcc80314ddffcb0981a9e9c5468662f8">android</a>
+<li>openCameraHardware()
+: <a class="el" href="namespaceandroid.html#24c243f7f9ba0d1d881be17ae06254a2">android</a>
+</ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/namespacemembers_type.html b/pdk/docs/namespacemembers_type.html
new file mode 100755
index 0000000..29c17f1
--- /dev/null
+++ b/pdk/docs/namespacemembers_type.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li class="current"><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="namespaces.html"><span>Namespace List</span></a></li>
+ <li class="current"><a href="namespacemembers.html"><span>Namespace Members</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="namespacemembers.html"><span>All</span></a></li>
+ <li><a href="namespacemembers_func.html"><span>Functions</span></a></li>
+ <li class="current"><a href="namespacemembers_type.html"><span>Typedefs</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+
+<p>
+<ul>
+<li>autofocus_callback
+: <a class="el" href="namespaceandroid.html#4dca8d8b824ca9a684358133da0ec8f2">android</a>
+<li>jpeg_callback
+: <a class="el" href="namespaceandroid.html#c21980d4be1e0cc458399ecf5374d473">android</a>
+<li>preview_callback
+: <a class="el" href="namespaceandroid.html#d32b08663d42356404e2eb971e271636">android</a>
+<li>raw_callback
+: <a class="el" href="namespaceandroid.html#a97926709e452d66360cb9b24736969e">android</a>
+<li>shutter_callback
+: <a class="el" href="namespaceandroid.html#04c83209c2627e2d303320712ca9ee65">android</a>
+</ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/namespaces.html b/pdk/docs/namespaces.html
new file mode 100755
index 0000000..23a9679
--- /dev/null
+++ b/pdk/docs/namespaces.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li class="current"><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li class="current"><a href="namespaces.html"><span>Namespace List</span></a></li>
+ <li><a href="namespacemembers.html"><span>Namespace Members</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+<h1>Namespace List</h1>Here is a list of all namespaces with brief descriptions:<table>
+ <tr><td class="indexkey"><a class="el" href="namespaceandroid.html">android</a></td><td class="indexvalue"></td></tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/power_management.html b/pdk/docs/power_management.html
index 91109be..eb510dd 100755
--- a/pdk/docs/power_management.html
+++ b/pdk/docs/power_management.html
@@ -2,11 +2,23 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
-<title>Android - Power Management</title>
+<title>Android - Porting Guide</title>
<script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=internal-codesite" type="text/javascript"></script>
<script src="http://code.google.com/js/jquery.js" type="text/javascript"></script>
<script type="text/javascript">var _tocPath_ = 'http://code.google.com/android/_toc.ezt';</script>
<script src="http://code.google.com/js/codesite.pack.01312008.js" type="text/javascript"></script>
+<script language="JavaScript">
+function resizeHeight() {
+ if(document.getElementById && !(document.all)) {
+ height= document.getElementById('doxygen').contentDocument.body.scrollHeight + 20;
+ document.getElementById('doxygen').style.height = height;
+ }
+ else if(document.all) {
+ height= document.frames('doxygen').document.body.scrollHeight + 20;
+ document.all.doxygen.style.height = height;
+ }
+}
+</script>
<link href="http://code.google.com/css/codesite.pack.01312008.css" type="text/css" rel="stylesheet">
</link>
@@ -33,6 +45,7 @@
<div id="skipto"> </div>
<div id="langpref">
<!--<a class="dropdown" href="/">English</a> <span>|</span> <a href="/more/">Site Directory</a> -->
+
</div>
<div id="gc-header">
<div id="logo"><a href="http://code.google.com/android/index.html"><img src="http://code.google.com/android/images/logo_android.gif" alt="Android"/></a></div>
@@ -51,6 +64,7 @@
}
</style>
</noscript>
+
<div id="searchForm2" class="searchForm2" style="display:none">
<form id="searchbox_001456098540849067467:6whlsytkdqg" action="http://www.google.com/cse">
<input type="hidden" name="cx" value="001456098540849067467:6whlsytkdqg" />
@@ -59,6 +73,7 @@
<input type="submit" name="sa" value="Search" title="Search"/>
<br/>
<div class="greytext">e.g. "ajax apis" or "open source"</div>
+
</form>
</div>
<!-- end searchForm2 -->
@@ -71,15 +86,18 @@
<div id="codesiteContent">
<a name="gc-topnav-anchor"></a>
<div id="gc-topnav">
+
<h1>Android Platform Development Kit</h1>
<ul class="gc-topnav-tabs">
<li id="sdk_link"> <a href="http://code.google.com/android/index.html" title="Android Software Development Kit">SDK</a> </li>
<li id="docs_link"> <a href="index.html" title="Official Android documentation">Docs</a> </li>
<li id="faq_link"> <a href="http://code.google.com/android/kb/index.html" title="Answers to frequently asked questions about Android">FAQ</a> </li>
+
<li> <a href="http://android-developers.blogspot.com/" title="Official Android blog">Blog</a> </li>
<li> <a href="http://code.google.com/android/groups.html" title="Android developer forum">Group</a> </li>
<li> <a href="http://code.google.com/android/terms.html" title="Android terms of service">Terms</a> </li>
- <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20power_management.html%20v0.3%20-%209%20June%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+ <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20power_management.html%20v0.6%20-%2025%20November%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+
</ul>
</div>
<!-- end gc-topnav -->
@@ -91,19 +109,18 @@
<h1><a href="index.html">Documentation</a></h1>
<ul>
<li> <strong>Introduction</strong>
+
<ul>
<li><a href="system_requirements.html">Device Requirements</a></li>
</ul>
</li>
<li> <strong>Dev Environment Setup</strong>
<ul>
- <li><a href="source_setup_guide.html">Host System Setup</a></li>
- <li><a href="getting_source_code.html">Getting Source Code</a></li>
- <li> <a href="intro_source_code.html">Source Code Overview</a></li>
<li><a href="build_system.html">Build System</a></li>
</ul>
</li>
<li> <strong>Basic Bring up</strong>
+
<ul>
<li><a href="build_new_device.html">Building New Device</a></li>
<li><a href="bring_up.html">Bring up</a></li>
@@ -111,26 +128,39 @@
<li><a href="display_drivers.html">Display Drivers</a></li>
</ul>
</li>
+
<li> <strong>Multimedia</strong>
<ul>
- <li><a href="audio_sub_system.html">Audio Subsystem</a></li>
+ <li><a href="audio_sub_system.html">Audio</a></li>
+ <li><a href="camera.html">Camera</a></li>
</ul>
</li>
<li> <strong>Power Management</strong>
+
<ul>
<li><a href="power_management.html">Power Management</a></li>
</ul>
</li>
+
+ <li> <strong>Networking</strong>
+ <ul>
+ <li><a href="wifi.html">Wi-Fi</a></li>
+ <li><a href="gps.html">GPS</a></li>
+ <li><a href="bluetooth.html">Bluetooth</a></li>
+ </ul>
+ </li>
+
<li> <strong>Telephony</strong>
<ul>
<li><a href="telephony.html">Radio Interface Layer</a></li>
+
</ul>
</li>
<li> <strong>Testing</strong>
<ul>
- <li><a href="instrumentation_framework.html">Instrumentation Framework</a></li>
<li><a href="instrumentation_testing.html">Instrumentation Testing</a></li>
</ul>
+
</li>
</ul>
</li>
@@ -163,7 +193,7 @@
<p>The image below illustrates the Android power management architecture. </p>
<p><img src='androidPMArchitecture.gif'></p>
-Solid elements represent Android blocks and dashed elements represent partner-specific proprietary blocks.
+Solid elements represent Android blocks and dashed elements represent partner-specific blocks.
@@ -275,7 +305,7 @@
pageTracker._trackPageview();
} catch(e) {}
</script>
-<div id="jd-build-id"> v0.3 - 9 June 2008</div>
+<div id="jd-build-id"> v0.6 - 25 November 2008</div>
</div></div></div></body>
</html>
diff --git a/pdk/docs/source_setup_guide.html b/pdk/docs/source_setup_guide.html
index 7a8cb9a..1588b29 100755
--- a/pdk/docs/source_setup_guide.html
+++ b/pdk/docs/source_setup_guide.html
@@ -2,11 +2,23 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
-<title>Android - Host System Setup</title>
+<title>Android - Porting Guide</title>
<script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=internal-codesite" type="text/javascript"></script>
<script src="http://code.google.com/js/jquery.js" type="text/javascript"></script>
<script type="text/javascript">var _tocPath_ = 'http://code.google.com/android/_toc.ezt';</script>
<script src="http://code.google.com/js/codesite.pack.01312008.js" type="text/javascript"></script>
+<script language="JavaScript">
+function resizeHeight() {
+ if(document.getElementById && !(document.all)) {
+ height= document.getElementById('doxygen').contentDocument.body.scrollHeight + 20;
+ document.getElementById('doxygen').style.height = height;
+ }
+ else if(document.all) {
+ height= document.frames('doxygen').document.body.scrollHeight + 20;
+ document.all.doxygen.style.height = height;
+ }
+}
+</script>
<link href="http://code.google.com/css/codesite.pack.01312008.css" type="text/css" rel="stylesheet">
</link>
@@ -33,6 +45,7 @@
<div id="skipto"> </div>
<div id="langpref">
<!--<a class="dropdown" href="/">English</a> <span>|</span> <a href="/more/">Site Directory</a> -->
+
</div>
<div id="gc-header">
<div id="logo"><a href="http://code.google.com/android/index.html"><img src="http://code.google.com/android/images/logo_android.gif" alt="Android"/></a></div>
@@ -51,6 +64,7 @@
}
</style>
</noscript>
+
<div id="searchForm2" class="searchForm2" style="display:none">
<form id="searchbox_001456098540849067467:6whlsytkdqg" action="http://www.google.com/cse">
<input type="hidden" name="cx" value="001456098540849067467:6whlsytkdqg" />
@@ -59,6 +73,7 @@
<input type="submit" name="sa" value="Search" title="Search"/>
<br/>
<div class="greytext">e.g. "ajax apis" or "open source"</div>
+
</form>
</div>
<!-- end searchForm2 -->
@@ -71,15 +86,18 @@
<div id="codesiteContent">
<a name="gc-topnav-anchor"></a>
<div id="gc-topnav">
+
<h1>Android Platform Development Kit</h1>
<ul class="gc-topnav-tabs">
<li id="sdk_link"> <a href="http://code.google.com/android/index.html" title="Android Software Development Kit">SDK</a> </li>
<li id="docs_link"> <a href="index.html" title="Official Android documentation">Docs</a> </li>
<li id="faq_link"> <a href="http://code.google.com/android/kb/index.html" title="Answers to frequently asked questions about Android">FAQ</a> </li>
+
<li> <a href="http://android-developers.blogspot.com/" title="Official Android blog">Blog</a> </li>
<li> <a href="http://code.google.com/android/groups.html" title="Android developer forum">Group</a> </li>
<li> <a href="http://code.google.com/android/terms.html" title="Android terms of service">Terms</a> </li>
- <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20source_setup_guide.html%20v0.3%20-%209%20June%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+ <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20index.html%20v0.5%20-%2025%20September%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+
</ul>
</div>
<!-- end gc-topnav -->
@@ -91,6 +109,7 @@
<h1><a href="index.html">Documentation</a></h1>
<ul>
<li> <strong>Introduction</strong>
+
<ul>
<li><a href="system_requirements.html">Device Requirements</a></li>
</ul>
@@ -98,12 +117,14 @@
<li> <strong>Dev Environment Setup</strong>
<ul>
<li><a href="source_setup_guide.html">Host System Setup</a></li>
+
<li><a href="getting_source_code.html">Getting Source Code</a></li>
<li> <a href="intro_source_code.html">Source Code Overview</a></li>
<li><a href="build_system.html">Build System</a></li>
</ul>
</li>
<li> <strong>Basic Bring up</strong>
+
<ul>
<li><a href="build_new_device.html">Building New Device</a></li>
<li><a href="bring_up.html">Bring up</a></li>
@@ -111,26 +132,39 @@
<li><a href="display_drivers.html">Display Drivers</a></li>
</ul>
</li>
+
<li> <strong>Multimedia</strong>
<ul>
<li><a href="audio_sub_system.html">Audio Subsystem</a></li>
+ <li><a href="camera.html">Camera</a></li>
</ul>
</li>
<li> <strong>Power Management</strong>
+
<ul>
<li><a href="power_management.html">Power Management</a></li>
</ul>
</li>
+
+ <li> <strong>Networking</strong>
+ <ul>
+ <li><a href="wifi.html">Wi-Fi</a></li>
+ <li><a href="gps.html">GPS</a></li>
+ <li><a href="bluetooth.html">Bluetooth</a></li>
+ </ul>
+ </li>
+
<li> <strong>Telephony</strong>
<ul>
<li><a href="telephony.html">Radio Interface Layer</a></li>
+
</ul>
</li>
<li> <strong>Testing</strong>
<ul>
- <li><a href="instrumentation_framework.html">Instrumentation Framework</a></li>
<li><a href="instrumentation_testing.html">Instrumentation Testing</a></li>
</ul>
+
</li>
</ul>
</li>
@@ -283,7 +317,7 @@
pageTracker._trackPageview();
} catch(e) {}
</script>
-<div id="jd-build-id"> v0.3 - 9 June 2008</div>
+<div id="jd-build-id"> v0.5 - 25 September 2008</div>
</div></div></div></body>
</html>
diff --git a/pdk/docs/struct_gps_callbacks.html b/pdk/docs/struct_gps_callbacks.html
new file mode 100755
index 0000000..42a148f
--- /dev/null
+++ b/pdk/docs/struct_gps_callbacks.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li class="current"><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="functions.html"><span>Data Fields</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+<h1>GpsCallbacks Struct Reference</h1><!-- doxytag: class="GpsCallbacks" -->GPS callback structure.
+<a href="#_details">More...</a>
+<p>
+<code>#include <<a class="el" href="gps_8h-source.html">gps.h</a>></code>
+<p>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Data Fields</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="el" href="gps_8h.html#88f19d3da70dc0e951b51091ce0631ae">gps_location_callback</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_callbacks.html#1f59b4f8eeaca50620f94761536dabd3">location_cb</a></td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="el" href="gps_8h.html#1d9ef60ab0b91f7c106867a6aa1e4412">gps_status_callback</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_callbacks.html#7b15a1bf4f9b989677fef84f4d8141df">status_cb</a></td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="el" href="gps_8h.html#67274e784834c6c2547f4b5344fc4ea9">gps_sv_status_callback</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_callbacks.html#fb34f60ad58e80de5c04790b107bb93d">sv_status_cb</a></td></tr>
+
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+GPS callback structure.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00175">175</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+<hr><h2>Field Documentation</h2>
+<a class="anchor" name="1f59b4f8eeaca50620f94761536dabd3"></a><!-- doxytag: member="GpsCallbacks::location_cb" ref="1f59b4f8eeaca50620f94761536dabd3" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="gps_8h.html#88f19d3da70dc0e951b51091ce0631ae">gps_location_callback</a> <a class="el" href="struct_gps_callbacks.html#1f59b4f8eeaca50620f94761536dabd3">GpsCallbacks::location_cb</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00176">176</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="7b15a1bf4f9b989677fef84f4d8141df"></a><!-- doxytag: member="GpsCallbacks::status_cb" ref="7b15a1bf4f9b989677fef84f4d8141df" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="gps_8h.html#1d9ef60ab0b91f7c106867a6aa1e4412">gps_status_callback</a> <a class="el" href="struct_gps_callbacks.html#7b15a1bf4f9b989677fef84f4d8141df">GpsCallbacks::status_cb</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00177">177</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="fb34f60ad58e80de5c04790b107bb93d"></a><!-- doxytag: member="GpsCallbacks::sv_status_cb" ref="fb34f60ad58e80de5c04790b107bb93d" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="gps_8h.html#67274e784834c6c2547f4b5344fc4ea9">gps_sv_status_callback</a> <a class="el" href="struct_gps_callbacks.html#fb34f60ad58e80de5c04790b107bb93d">GpsCallbacks::sv_status_cb</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00178">178</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<hr>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="gps_8h-source.html">gps.h</a></ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/struct_gps_interface.html b/pdk/docs/struct_gps_interface.html
new file mode 100755
index 0000000..f99e824
--- /dev/null
+++ b/pdk/docs/struct_gps_interface.html
@@ -0,0 +1,233 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li class="current"><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="functions.html"><span>Data Fields</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+<h1>GpsInterface Struct Reference</h1><!-- doxytag: class="GpsInterface" -->Represents the standard GPS interface.
+<a href="#_details">More...</a>
+<p>
+<code>#include <<a class="el" href="gps_8h-source.html">gps.h</a>></code>
+<p>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Data Fields</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int(* </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_interface.html#d5139fa13b75108bdedd8a2717f37135">init</a> )(<a class="el" href="struct_gps_callbacks.html">GpsCallbacks</a> *callbacks)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Opens the interface and provides the callback routines to the implemenation of this interface. <a href="#d5139fa13b75108bdedd8a2717f37135"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int(* </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_interface.html#2b212721e0d160e24944330b2d830790">start</a> )(void)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Starts navigating. <a href="#2b212721e0d160e24944330b2d830790"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int(* </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_interface.html#d20b0cfcbf976d8cec17bf4ea0a027f1">stop</a> )(void)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Stops navigating. <a href="#d20b0cfcbf976d8cec17bf4ea0a027f1"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void(* </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_interface.html#1e727f5862ae7132f12af44ebdfa76b2">set_fix_frequency</a> )(int frequency)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Sets requested frequency of fixes in seconds. <a href="#1e727f5862ae7132f12af44ebdfa76b2"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void(* </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_interface.html#2911808e36c70259dc0db162de02dc13">cleanup</a> )(void)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Closes the interface. <a href="#2911808e36c70259dc0db162de02dc13"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int(* </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_interface.html#e731891e96a916271a4275eaaea47ad8">inject_time</a> )(<a class="el" href="gps_8h.html#f2b0ea531a44c010f81a4abd27504c15">GpsUtcTime</a> time, int64_t timeReference, int uncertainty)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Injects the current time. <a href="#e731891e96a916271a4275eaaea47ad8"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void(* </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_interface.html#a3a9b81a8a719b628ac8049344f50b58">delete_aiding_data</a> )(<a class="el" href="gps_8h.html#93f0283aeabd20211499991a29db7377">GpsAidingData</a> flags)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Specifies that the next call to start will not use the information defined in the flags. <a href="#a3a9b81a8a719b628ac8049344f50b58"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int(* </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_interface.html#924bff47462a773b669d310d87b75734">set_position_mode</a> )(<a class="el" href="gps_8h.html#2461a6f0dd56a1f7dc94e93207a1f740">GpsPositionMode</a> mode, int fix_frequency)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">fix_frequency represents the time between fixes in seconds. <a href="#924bff47462a773b669d310d87b75734"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">const void *(* </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_interface.html#19af32bd9d01ebbcdb196e36514b0e98">get_extension</a> )(const char *name)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Get a pointer to extension information. <a href="#19af32bd9d01ebbcdb196e36514b0e98"></a><br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Represents the standard GPS interface.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00183">183</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+<hr><h2>Field Documentation</h2>
+<a class="anchor" name="d5139fa13b75108bdedd8a2717f37135"></a><!-- doxytag: member="GpsInterface::init" ref="d5139fa13b75108bdedd8a2717f37135" args=")(GpsCallbacks *callbacks)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int(* <a class="el" href="struct_gps_interface.html#d5139fa13b75108bdedd8a2717f37135">GpsInterface::init</a>)(<a class="el" href="struct_gps_callbacks.html">GpsCallbacks</a> *callbacks) </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Opens the interface and provides the callback routines to the implemenation of this interface.
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="2b212721e0d160e24944330b2d830790"></a><!-- doxytag: member="GpsInterface::start" ref="2b212721e0d160e24944330b2d830790" args=")(void)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int(* <a class="el" href="struct_gps_interface.html#2b212721e0d160e24944330b2d830790">GpsInterface::start</a>)(void) </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Starts navigating.
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="d20b0cfcbf976d8cec17bf4ea0a027f1"></a><!-- doxytag: member="GpsInterface::stop" ref="d20b0cfcbf976d8cec17bf4ea0a027f1" args=")(void)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int(* <a class="el" href="struct_gps_interface.html#d20b0cfcbf976d8cec17bf4ea0a027f1">GpsInterface::stop</a>)(void) </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Stops navigating.
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="1e727f5862ae7132f12af44ebdfa76b2"></a><!-- doxytag: member="GpsInterface::set_fix_frequency" ref="1e727f5862ae7132f12af44ebdfa76b2" args=")(int frequency)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">void(* <a class="el" href="struct_gps_interface.html#1e727f5862ae7132f12af44ebdfa76b2">GpsInterface::set_fix_frequency</a>)(int frequency) </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Sets requested frequency of fixes in seconds.
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="2911808e36c70259dc0db162de02dc13"></a><!-- doxytag: member="GpsInterface::cleanup" ref="2911808e36c70259dc0db162de02dc13" args=")(void)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">void(* <a class="el" href="struct_gps_interface.html#2911808e36c70259dc0db162de02dc13">GpsInterface::cleanup</a>)(void) </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Closes the interface.
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="e731891e96a916271a4275eaaea47ad8"></a><!-- doxytag: member="GpsInterface::inject_time" ref="e731891e96a916271a4275eaaea47ad8" args=")(GpsUtcTime time, int64_t timeReference, int uncertainty)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int(* <a class="el" href="struct_gps_interface.html#e731891e96a916271a4275eaaea47ad8">GpsInterface::inject_time</a>)(<a class="el" href="gps_8h.html#f2b0ea531a44c010f81a4abd27504c15">GpsUtcTime</a> time, int64_t timeReference, int uncertainty) </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Injects the current time.
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="a3a9b81a8a719b628ac8049344f50b58"></a><!-- doxytag: member="GpsInterface::delete_aiding_data" ref="a3a9b81a8a719b628ac8049344f50b58" args=")(GpsAidingData flags)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">void(* <a class="el" href="struct_gps_interface.html#a3a9b81a8a719b628ac8049344f50b58">GpsInterface::delete_aiding_data</a>)(<a class="el" href="gps_8h.html#93f0283aeabd20211499991a29db7377">GpsAidingData</a> flags) </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Specifies that the next call to start will not use the information defined in the flags.
+<p>
+GPS_DELETE_ALL is passed for a cold start.
+</div>
+</div><p>
+<a class="anchor" name="924bff47462a773b669d310d87b75734"></a><!-- doxytag: member="GpsInterface::set_position_mode" ref="924bff47462a773b669d310d87b75734" args=")(GpsPositionMode mode, int fix_frequency)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int(* <a class="el" href="struct_gps_interface.html#924bff47462a773b669d310d87b75734">GpsInterface::set_position_mode</a>)(<a class="el" href="gps_8h.html#2461a6f0dd56a1f7dc94e93207a1f740">GpsPositionMode</a> mode, int fix_frequency) </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+fix_frequency represents the time between fixes in seconds.
+<p>
+Set fix_frequency to zero for a single-shot fix.
+</div>
+</div><p>
+<a class="anchor" name="19af32bd9d01ebbcdb196e36514b0e98"></a><!-- doxytag: member="GpsInterface::get_extension" ref="19af32bd9d01ebbcdb196e36514b0e98" args=")(const char *name)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">const void*(* <a class="el" href="struct_gps_interface.html#19af32bd9d01ebbcdb196e36514b0e98">GpsInterface::get_extension</a>)(const char *name) </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get a pointer to extension information.
+<p>
+
+</div>
+</div><p>
+<hr>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="gps_8h-source.html">gps.h</a></ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/struct_gps_location.html b/pdk/docs/struct_gps_location.html
new file mode 100755
index 0000000..33a61fd
--- /dev/null
+++ b/pdk/docs/struct_gps_location.html
@@ -0,0 +1,229 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li class="current"><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="functions.html"><span>Data Fields</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+<h1>GpsLocation Struct Reference</h1><!-- doxytag: class="GpsLocation" -->Represents a location.
+<a href="#_details">More...</a>
+<p>
+<code>#include <<a class="el" href="gps_8h-source.html">gps.h</a>></code>
+<p>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Data Fields</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">uint16_t </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_location.html#07d55fee34dc28cff50062e9ac42c717">flags</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Contains GpsLocationFlags bits. <a href="#07d55fee34dc28cff50062e9ac42c717"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">double </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_location.html#3a7da06efae47c66428fa2815a3eb4bd">latitude</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Represents latitude in degrees. <a href="#3a7da06efae47c66428fa2815a3eb4bd"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">double </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_location.html#3672d2d19087d62d7ea9b0b71418da40">longitude</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Represents longitude in degrees. <a href="#3672d2d19087d62d7ea9b0b71418da40"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">double </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_location.html#cb3cc5ad378a6a3864e47ae67df38778">altitude</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Represents altitude in meters above the WGS 84 reference ellipsoid. <a href="#cb3cc5ad378a6a3864e47ae67df38778"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">float </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_location.html#38ae20b9c5e7be995513dce25ed87016">speed</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Represents speed in meters per second. <a href="#38ae20b9c5e7be995513dce25ed87016"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">float </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_location.html#b71bf9b61cf55f10ffcf34ba1654d082">bearing</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Represents heading in degrees. <a href="#b71bf9b61cf55f10ffcf34ba1654d082"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">float </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_location.html#801ec0db8ee69fa263a63528876d773b">accuracy</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Represents expected accuracy in meters. <a href="#801ec0db8ee69fa263a63528876d773b"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="el" href="gps_8h.html#f2b0ea531a44c010f81a4abd27504c15">GpsUtcTime</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_location.html#3e16861f64869d6f0e15e4300bb2658b">timestamp</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Timestamp for the location fix. <a href="#3e16861f64869d6f0e15e4300bb2658b"></a><br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Represents a location.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00103">103</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+<hr><h2>Field Documentation</h2>
+<a class="anchor" name="07d55fee34dc28cff50062e9ac42c717"></a><!-- doxytag: member="GpsLocation::flags" ref="07d55fee34dc28cff50062e9ac42c717" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">uint16_t <a class="el" href="struct_gps_location.html#07d55fee34dc28cff50062e9ac42c717">GpsLocation::flags</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Contains GpsLocationFlags bits.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00105">105</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="3a7da06efae47c66428fa2815a3eb4bd"></a><!-- doxytag: member="GpsLocation::latitude" ref="3a7da06efae47c66428fa2815a3eb4bd" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">double <a class="el" href="struct_gps_location.html#3a7da06efae47c66428fa2815a3eb4bd">GpsLocation::latitude</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Represents latitude in degrees.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00107">107</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="3672d2d19087d62d7ea9b0b71418da40"></a><!-- doxytag: member="GpsLocation::longitude" ref="3672d2d19087d62d7ea9b0b71418da40" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">double <a class="el" href="struct_gps_location.html#3672d2d19087d62d7ea9b0b71418da40">GpsLocation::longitude</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Represents longitude in degrees.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00109">109</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="cb3cc5ad378a6a3864e47ae67df38778"></a><!-- doxytag: member="GpsLocation::altitude" ref="cb3cc5ad378a6a3864e47ae67df38778" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">double <a class="el" href="struct_gps_location.html#cb3cc5ad378a6a3864e47ae67df38778">GpsLocation::altitude</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Represents altitude in meters above the WGS 84 reference ellipsoid.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00112">112</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="38ae20b9c5e7be995513dce25ed87016"></a><!-- doxytag: member="GpsLocation::speed" ref="38ae20b9c5e7be995513dce25ed87016" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">float <a class="el" href="struct_gps_location.html#38ae20b9c5e7be995513dce25ed87016">GpsLocation::speed</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Represents speed in meters per second.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00114">114</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="b71bf9b61cf55f10ffcf34ba1654d082"></a><!-- doxytag: member="GpsLocation::bearing" ref="b71bf9b61cf55f10ffcf34ba1654d082" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">float <a class="el" href="struct_gps_location.html#b71bf9b61cf55f10ffcf34ba1654d082">GpsLocation::bearing</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Represents heading in degrees.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00116">116</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="801ec0db8ee69fa263a63528876d773b"></a><!-- doxytag: member="GpsLocation::accuracy" ref="801ec0db8ee69fa263a63528876d773b" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">float <a class="el" href="struct_gps_location.html#801ec0db8ee69fa263a63528876d773b">GpsLocation::accuracy</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Represents expected accuracy in meters.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00118">118</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="3e16861f64869d6f0e15e4300bb2658b"></a><!-- doxytag: member="GpsLocation::timestamp" ref="3e16861f64869d6f0e15e4300bb2658b" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="gps_8h.html#f2b0ea531a44c010f81a4abd27504c15">GpsUtcTime</a> <a class="el" href="struct_gps_location.html#3e16861f64869d6f0e15e4300bb2658b">GpsLocation::timestamp</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Timestamp for the location fix.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00120">120</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<hr>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="gps_8h-source.html">gps.h</a></ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/struct_gps_status.html b/pdk/docs/struct_gps_status.html
new file mode 100755
index 0000000..c4a767f
--- /dev/null
+++ b/pdk/docs/struct_gps_status.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li class="current"><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="functions.html"><span>Data Fields</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+<h1>GpsStatus Struct Reference</h1><!-- doxytag: class="GpsStatus" -->Represents the status.
+<a href="#_details">More...</a>
+<p>
+<code>#include <<a class="el" href="gps_8h-source.html">gps.h</a>></code>
+<p>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Data Fields</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="el" href="gps_8h.html#de8fa0020d3aa1748a8e26759b768ec5">GpsStatusValue</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_status.html#64c9e8cd609d97533bee5c5e8ca78608">status</a></td></tr>
+
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Represents the status.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00124">124</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+<hr><h2>Field Documentation</h2>
+<a class="anchor" name="64c9e8cd609d97533bee5c5e8ca78608"></a><!-- doxytag: member="GpsStatus::status" ref="64c9e8cd609d97533bee5c5e8ca78608" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="gps_8h.html#de8fa0020d3aa1748a8e26759b768ec5">GpsStatusValue</a> <a class="el" href="struct_gps_status.html#64c9e8cd609d97533bee5c5e8ca78608">GpsStatus::status</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00125">125</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<hr>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="gps_8h-source.html">gps.h</a></ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/struct_gps_sv_info.html b/pdk/docs/struct_gps_sv_info.html
new file mode 100755
index 0000000..b7ee8a1
--- /dev/null
+++ b/pdk/docs/struct_gps_sv_info.html
@@ -0,0 +1,141 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li class="current"><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="functions.html"><span>Data Fields</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+<h1>GpsSvInfo Struct Reference</h1><!-- doxytag: class="GpsSvInfo" -->Represents SV information.
+<a href="#_details">More...</a>
+<p>
+<code>#include <<a class="el" href="gps_8h-source.html">gps.h</a>></code>
+<p>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Data Fields</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_sv_info.html#5c94e86f2efc3ed08fb5a40735a2440b">prn</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Pseudo-random number for the SV. <a href="#5c94e86f2efc3ed08fb5a40735a2440b"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">float </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_sv_info.html#eebf16140beb95390733529bd5e7db58">snr</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Signal to noise ratio. <a href="#eebf16140beb95390733529bd5e7db58"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">float </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_sv_info.html#0634009d0476b2f06f27568b0722a04d">elevation</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Elevation of SV in degrees. <a href="#0634009d0476b2f06f27568b0722a04d"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">float </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_sv_info.html#94755ad36e31a012269459d5a4ef0594">azimuth</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Azimuth of SV in degrees. <a href="#94755ad36e31a012269459d5a4ef0594"></a><br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Represents SV information.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00129">129</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+<hr><h2>Field Documentation</h2>
+<a class="anchor" name="5c94e86f2efc3ed08fb5a40735a2440b"></a><!-- doxytag: member="GpsSvInfo::prn" ref="5c94e86f2efc3ed08fb5a40735a2440b" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int <a class="el" href="struct_gps_sv_info.html#5c94e86f2efc3ed08fb5a40735a2440b">GpsSvInfo::prn</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Pseudo-random number for the SV.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00131">131</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="eebf16140beb95390733529bd5e7db58"></a><!-- doxytag: member="GpsSvInfo::snr" ref="eebf16140beb95390733529bd5e7db58" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">float <a class="el" href="struct_gps_sv_info.html#eebf16140beb95390733529bd5e7db58">GpsSvInfo::snr</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Signal to noise ratio.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00133">133</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="0634009d0476b2f06f27568b0722a04d"></a><!-- doxytag: member="GpsSvInfo::elevation" ref="0634009d0476b2f06f27568b0722a04d" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">float <a class="el" href="struct_gps_sv_info.html#0634009d0476b2f06f27568b0722a04d">GpsSvInfo::elevation</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Elevation of SV in degrees.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00135">135</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="94755ad36e31a012269459d5a4ef0594"></a><!-- doxytag: member="GpsSvInfo::azimuth" ref="94755ad36e31a012269459d5a4ef0594" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">float <a class="el" href="struct_gps_sv_info.html#94755ad36e31a012269459d5a4ef0594">GpsSvInfo::azimuth</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Azimuth of SV in degrees.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00137">137</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<hr>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="gps_8h-source.html">gps.h</a></ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/struct_gps_sv_status.html b/pdk/docs/struct_gps_sv_status.html
new file mode 100755
index 0000000..c18fead
--- /dev/null
+++ b/pdk/docs/struct_gps_sv_status.html
@@ -0,0 +1,163 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li class="current"><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="functions.html"><span>Data Fields</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+<h1>GpsSvStatus Struct Reference</h1><!-- doxytag: class="GpsSvStatus" -->Represents SV status.
+<a href="#_details">More...</a>
+<p>
+<code>#include <<a class="el" href="gps_8h-source.html">gps.h</a>></code>
+<p>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Data Fields</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_sv_status.html#b90eb63a499039de996c95d98afad545">num_svs</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Number of SVs currently visible. <a href="#b90eb63a499039de996c95d98afad545"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="el" href="struct_gps_sv_info.html">GpsSvInfo</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_sv_status.html#7a3fe2114e7a603b96fd9675adf0c5b5">sv_list</a> [GPS_MAX_SVS]</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Contains an array of SV information. <a href="#7a3fe2114e7a603b96fd9675adf0c5b5"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_sv_status.html#4751f70f8e275241dece99db0df4ab5b">ephemeris_mask</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Represents a bit mask indicating which SVs have ephemeris data. <a href="#4751f70f8e275241dece99db0df4ab5b"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_sv_status.html#6ed4b741a9882ecc2852e94e8ad60310">almanac_mask</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Represents a bit mask indicating which SVs have almanac data. <a href="#6ed4b741a9882ecc2852e94e8ad60310"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_sv_status.html#9090a26639d97eec2b59bcd0446659c0">used_in_fix_mask</a></td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Represents a bit mask indicating which SVs were used for computing the most recent position fix. <a href="#9090a26639d97eec2b59bcd0446659c0"></a><br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Represents SV status.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00141">141</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+<hr><h2>Field Documentation</h2>
+<a class="anchor" name="b90eb63a499039de996c95d98afad545"></a><!-- doxytag: member="GpsSvStatus::num_svs" ref="b90eb63a499039de996c95d98afad545" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int <a class="el" href="struct_gps_sv_status.html#b90eb63a499039de996c95d98afad545">GpsSvStatus::num_svs</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Number of SVs currently visible.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00143">143</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="7a3fe2114e7a603b96fd9675adf0c5b5"></a><!-- doxytag: member="GpsSvStatus::sv_list" ref="7a3fe2114e7a603b96fd9675adf0c5b5" args="[GPS_MAX_SVS]" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="struct_gps_sv_info.html">GpsSvInfo</a> <a class="el" href="struct_gps_sv_status.html#7a3fe2114e7a603b96fd9675adf0c5b5">GpsSvStatus::sv_list</a>[GPS_MAX_SVS] </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Contains an array of SV information.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00146">146</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="4751f70f8e275241dece99db0df4ab5b"></a><!-- doxytag: member="GpsSvStatus::ephemeris_mask" ref="4751f70f8e275241dece99db0df4ab5b" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">uint32_t <a class="el" href="struct_gps_sv_status.html#4751f70f8e275241dece99db0df4ab5b">GpsSvStatus::ephemeris_mask</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Represents a bit mask indicating which SVs have ephemeris data.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00151">151</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="6ed4b741a9882ecc2852e94e8ad60310"></a><!-- doxytag: member="GpsSvStatus::almanac_mask" ref="6ed4b741a9882ecc2852e94e8ad60310" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">uint32_t <a class="el" href="struct_gps_sv_status.html#6ed4b741a9882ecc2852e94e8ad60310">GpsSvStatus::almanac_mask</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Represents a bit mask indicating which SVs have almanac data.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00156">156</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<a class="anchor" name="9090a26639d97eec2b59bcd0446659c0"></a><!-- doxytag: member="GpsSvStatus::used_in_fix_mask" ref="9090a26639d97eec2b59bcd0446659c0" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">uint32_t <a class="el" href="struct_gps_sv_status.html#9090a26639d97eec2b59bcd0446659c0">GpsSvStatus::used_in_fix_mask</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Represents a bit mask indicating which SVs were used for computing the most recent position fix.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00162">162</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<hr>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="gps_8h-source.html">gps.h</a></ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/struct_gps_xtra_callbacks.html b/pdk/docs/struct_gps_xtra_callbacks.html
new file mode 100755
index 0000000..08130e3
--- /dev/null
+++ b/pdk/docs/struct_gps_xtra_callbacks.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li class="current"><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="functions.html"><span>Data Fields</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+<h1>GpsXtraCallbacks Struct Reference</h1><!-- doxytag: class="GpsXtraCallbacks" -->Callback structure for the XTRA interface.
+<a href="#_details">More...</a>
+<p>
+<code>#include <<a class="el" href="gps_8h-source.html">gps.h</a>></code>
+<p>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Data Fields</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="el" href="gps_8h.html#08fcfb3f85c2ac3008c9c73cf9136515">gps_xtra_download_request</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_xtra_callbacks.html#7e879ba4c3e32c52eaa0fb04fb9c226f">download_request_cb</a></td></tr>
+
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Callback structure for the XTRA interface.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00229">229</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+<hr><h2>Field Documentation</h2>
+<a class="anchor" name="7e879ba4c3e32c52eaa0fb04fb9c226f"></a><!-- doxytag: member="GpsXtraCallbacks::download_request_cb" ref="7e879ba4c3e32c52eaa0fb04fb9c226f" args="" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="gps_8h.html#08fcfb3f85c2ac3008c9c73cf9136515">gps_xtra_download_request</a> <a class="el" href="struct_gps_xtra_callbacks.html#7e879ba4c3e32c52eaa0fb04fb9c226f">GpsXtraCallbacks::download_request_cb</a> </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00230">230</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+
+</div>
+</div><p>
+<hr>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="gps_8h-source.html">gps.h</a></ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/struct_gps_xtra_interface.html b/pdk/docs/struct_gps_xtra_interface.html
new file mode 100755
index 0000000..d21fa10
--- /dev/null
+++ b/pdk/docs/struct_gps_xtra_interface.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li class="current"><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+ <div class="tabs">
+ <ul>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li><a href="functions.html"><span>Data Fields</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+<h1>GpsXtraInterface Struct Reference</h1><!-- doxytag: class="GpsXtraInterface" -->Extended interface for XTRA support.
+<a href="#_details">More...</a>
+<p>
+<code>#include <<a class="el" href="gps_8h-source.html">gps.h</a>></code>
+<p>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Data Fields</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int(* </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_xtra_interface.html#5532e662c68e1d3df7db86570df96bf0">init</a> )(<a class="el" href="struct_gps_xtra_callbacks.html">GpsXtraCallbacks</a> *callbacks)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Opens the XTRA interface and provides the callback routines to the implemenation of this interface. <a href="#5532e662c68e1d3df7db86570df96bf0"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int(* </td><td class="memItemRight" valign="bottom"><a class="el" href="struct_gps_xtra_interface.html#2b1962c8a5a2751702937cf469dc7435">inject_xtra_data</a> )(char *data, int length)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Injects XTRA data into the GPS. <a href="#2b1962c8a5a2751702937cf469dc7435"></a><br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Extended interface for XTRA support.
+<p>
+
+<p>Definition at line <a class="el" href="gps_8h-source.html#l00234">234</a> of file <a class="el" href="gps_8h-source.html">gps.h</a>.</p>
+<hr><h2>Field Documentation</h2>
+<a class="anchor" name="5532e662c68e1d3df7db86570df96bf0"></a><!-- doxytag: member="GpsXtraInterface::init" ref="5532e662c68e1d3df7db86570df96bf0" args=")(GpsXtraCallbacks *callbacks)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int(* <a class="el" href="struct_gps_xtra_interface.html#5532e662c68e1d3df7db86570df96bf0">GpsXtraInterface::init</a>)(<a class="el" href="struct_gps_xtra_callbacks.html">GpsXtraCallbacks</a> *callbacks) </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Opens the XTRA interface and provides the callback routines to the implemenation of this interface.
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="2b1962c8a5a2751702937cf469dc7435"></a><!-- doxytag: member="GpsXtraInterface::inject_xtra_data" ref="2b1962c8a5a2751702937cf469dc7435" args=")(char *data, int length)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int(* <a class="el" href="struct_gps_xtra_interface.html#2b1962c8a5a2751702937cf469dc7435">GpsXtraInterface::inject_xtra_data</a>)(char *data, int length) </td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Injects XTRA data into the GPS.
+<p>
+
+</div>
+</div><p>
+<hr>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="gps_8h-source.html">gps.h</a></ul>
+</div>
+</body>
+</html>
diff --git a/pdk/docs/system_requirements.html b/pdk/docs/system_requirements.html
index d4a0104..2f236cf 100755
--- a/pdk/docs/system_requirements.html
+++ b/pdk/docs/system_requirements.html
@@ -2,11 +2,23 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
-<title>Android - Device Requirements</title>
+<title>Android - Porting Guide</title>
<script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=internal-codesite" type="text/javascript"></script>
<script src="http://code.google.com/js/jquery.js" type="text/javascript"></script>
<script type="text/javascript">var _tocPath_ = 'http://code.google.com/android/_toc.ezt';</script>
<script src="http://code.google.com/js/codesite.pack.01312008.js" type="text/javascript"></script>
+<script language="JavaScript">
+function resizeHeight() {
+ if(document.getElementById && !(document.all)) {
+ height= document.getElementById('doxygen').contentDocument.body.scrollHeight + 20;
+ document.getElementById('doxygen').style.height = height;
+ }
+ else if(document.all) {
+ height= document.frames('doxygen').document.body.scrollHeight + 20;
+ document.all.doxygen.style.height = height;
+ }
+}
+</script>
<link href="http://code.google.com/css/codesite.pack.01312008.css" type="text/css" rel="stylesheet">
</link>
@@ -33,6 +45,7 @@
<div id="skipto"> </div>
<div id="langpref">
<!--<a class="dropdown" href="/">English</a> <span>|</span> <a href="/more/">Site Directory</a> -->
+
</div>
<div id="gc-header">
<div id="logo"><a href="http://code.google.com/android/index.html"><img src="http://code.google.com/android/images/logo_android.gif" alt="Android"/></a></div>
@@ -51,6 +64,7 @@
}
</style>
</noscript>
+
<div id="searchForm2" class="searchForm2" style="display:none">
<form id="searchbox_001456098540849067467:6whlsytkdqg" action="http://www.google.com/cse">
<input type="hidden" name="cx" value="001456098540849067467:6whlsytkdqg" />
@@ -59,6 +73,7 @@
<input type="submit" name="sa" value="Search" title="Search"/>
<br/>
<div class="greytext">e.g. "ajax apis" or "open source"</div>
+
</form>
</div>
<!-- end searchForm2 -->
@@ -71,15 +86,18 @@
<div id="codesiteContent">
<a name="gc-topnav-anchor"></a>
<div id="gc-topnav">
+
<h1>Android Platform Development Kit</h1>
<ul class="gc-topnav-tabs">
<li id="sdk_link"> <a href="http://code.google.com/android/index.html" title="Android Software Development Kit">SDK</a> </li>
<li id="docs_link"> <a href="index.html" title="Official Android documentation">Docs</a> </li>
<li id="faq_link"> <a href="http://code.google.com/android/kb/index.html" title="Answers to frequently asked questions about Android">FAQ</a> </li>
+
<li> <a href="http://android-developers.blogspot.com/" title="Official Android blog">Blog</a> </li>
<li> <a href="http://code.google.com/android/groups.html" title="Android developer forum">Group</a> </li>
<li> <a href="http://code.google.com/android/terms.html" title="Android terms of service">Terms</a> </li>
- <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20system_requirements.html%20v0.3%20-%209%20June%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+ <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20system_requirements.html%20v0.6%20-%2025%20November%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+
</ul>
</div>
<!-- end gc-topnav -->
@@ -91,19 +109,18 @@
<h1><a href="index.html">Documentation</a></h1>
<ul>
<li> <strong>Introduction</strong>
+
<ul>
<li><a href="system_requirements.html">Device Requirements</a></li>
</ul>
</li>
<li> <strong>Dev Environment Setup</strong>
<ul>
- <li><a href="source_setup_guide.html">Host System Setup</a></li>
- <li><a href="getting_source_code.html">Getting Source Code</a></li>
- <li> <a href="intro_source_code.html">Source Code Overview</a></li>
<li><a href="build_system.html">Build System</a></li>
</ul>
</li>
<li> <strong>Basic Bring up</strong>
+
<ul>
<li><a href="build_new_device.html">Building New Device</a></li>
<li><a href="bring_up.html">Bring up</a></li>
@@ -111,26 +128,39 @@
<li><a href="display_drivers.html">Display Drivers</a></li>
</ul>
</li>
+
<li> <strong>Multimedia</strong>
<ul>
- <li><a href="audio_sub_system.html">Audio Subsystem</a></li>
+ <li><a href="audio_sub_system.html">Audio</a></li>
+ <li><a href="camera.html">Camera</a></li>
</ul>
</li>
<li> <strong>Power Management</strong>
+
<ul>
<li><a href="power_management.html">Power Management</a></li>
</ul>
</li>
+
+ <li> <strong>Networking</strong>
+ <ul>
+ <li><a href="wifi.html">Wi-Fi</a></li>
+ <li><a href="gps.html">GPS</a></li>
+ <li><a href="bluetooth.html">Bluetooth</a></li>
+ </ul>
+ </li>
+
<li> <strong>Telephony</strong>
<ul>
<li><a href="telephony.html">Radio Interface Layer</a></li>
+
</ul>
</li>
<li> <strong>Testing</strong>
<ul>
- <li><a href="instrumentation_framework.html">Instrumentation Framework</a></li>
<li><a href="instrumentation_testing.html">Instrumentation Testing</a></li>
</ul>
+
</li>
</ul>
</li>
@@ -168,7 +198,7 @@
</tr>
<tr>
<td>Primary Display </td>
- <td>QVGA TFT LCD or larger, 16-bit color or better</td>
+ <td>HVGA required</td>
<td>The current Android interface targets a touch-based HVGA resolution display with a touch-interface no smaller than 2.8 inches in size. However, smaller displays will suffice for initial porting.</td>
</tr>
<tr>
@@ -226,7 +256,7 @@
pageTracker._trackPageview();
} catch(e) {}
</script>
-<div id="jd-build-id"> v0.3 - 9 June 2008</div>
+<div id="jd-build-id"> v0.6 - 25 November 2008</div>
</div></div></div></body>
</html>
diff --git a/pdk/docs/tab_b.gif b/pdk/docs/tab_b.gif
new file mode 100755
index 0000000..0d62348
--- /dev/null
+++ b/pdk/docs/tab_b.gif
Binary files differ
diff --git a/pdk/docs/tab_l.gif b/pdk/docs/tab_l.gif
new file mode 100755
index 0000000..9b1e633
--- /dev/null
+++ b/pdk/docs/tab_l.gif
Binary files differ
diff --git a/pdk/docs/tab_r.gif b/pdk/docs/tab_r.gif
new file mode 100755
index 0000000..ce9dd9f
--- /dev/null
+++ b/pdk/docs/tab_r.gif
Binary files differ
diff --git a/pdk/docs/tabs.css b/pdk/docs/tabs.css
new file mode 100755
index 0000000..95f00a9
--- /dev/null
+++ b/pdk/docs/tabs.css
@@ -0,0 +1,102 @@
+/* tabs styles, based on http://www.alistapart.com/articles/slidingdoors */
+
+DIV.tabs
+{
+ float : left;
+ width : 100%;
+ background : url("tab_b.gif") repeat-x bottom;
+ margin-bottom : 4px;
+}
+
+DIV.tabs UL
+{
+ margin : 0px;
+ padding-left : 10px;
+ list-style : none;
+}
+
+DIV.tabs LI, DIV.tabs FORM
+{
+ display : inline;
+ margin : 0px;
+ padding : 0px;
+}
+
+DIV.tabs FORM
+{
+ float : right;
+}
+
+DIV.tabs A
+{
+ float : left;
+ background : url("tab_r.gif") no-repeat right top;
+ border-bottom : 1px solid #84B0C7;
+ font-size : x-small;
+ font-weight : bold;
+ text-decoration : none;
+}
+
+DIV.tabs A:hover
+{
+ background-position: 100% -150px;
+}
+
+DIV.tabs A:link, DIV.tabs A:visited,
+DIV.tabs A:active, DIV.tabs A:hover
+{
+ color: #1A419D;
+}
+
+DIV.tabs SPAN
+{
+ float : left;
+ display : block;
+ background : url("tab_l.gif") no-repeat left top;
+ padding : 5px 9px;
+ white-space : nowrap;
+}
+
+DIV.tabs INPUT
+{
+ float : right;
+ display : inline;
+ font-size : 1em;
+}
+
+DIV.tabs TD
+{
+ font-size : x-small;
+ font-weight : bold;
+ text-decoration : none;
+}
+
+
+
+/* Commented Backslash Hack hides rule from IE5-Mac \*/
+DIV.tabs SPAN {float : none;}
+/* End IE5-Mac hack */
+
+DIV.tabs A:hover SPAN
+{
+ background-position: 0% -150px;
+}
+
+DIV.tabs LI.current A
+{
+ background-position: 100% -150px;
+ border-width : 0px;
+}
+
+DIV.tabs LI.current SPAN
+{
+ background-position: 0% -150px;
+ padding-bottom : 6px;
+}
+
+DIV.navpath
+{
+ background : none;
+ border : none;
+ border-bottom : 1px solid #84B0C7;
+}
diff --git a/pdk/docs/telephony.html b/pdk/docs/telephony.html
index 9a18888..d4826f6 100755
--- a/pdk/docs/telephony.html
+++ b/pdk/docs/telephony.html
@@ -2,11 +2,23 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
-<title>Android - Radio Layer Interface</title>
+<title>Android - Porting Guide</title>
<script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=internal-codesite" type="text/javascript"></script>
<script src="http://code.google.com/js/jquery.js" type="text/javascript"></script>
<script type="text/javascript">var _tocPath_ = 'http://code.google.com/android/_toc.ezt';</script>
<script src="http://code.google.com/js/codesite.pack.01312008.js" type="text/javascript"></script>
+<script language="JavaScript">
+function resizeHeight() {
+ if(document.getElementById && !(document.all)) {
+ height= document.getElementById('doxygen').contentDocument.body.scrollHeight + 20;
+ document.getElementById('doxygen').style.height = height;
+ }
+ else if(document.all) {
+ height= document.frames('doxygen').document.body.scrollHeight + 20;
+ document.all.doxygen.style.height = height;
+ }
+}
+</script>
<link href="http://code.google.com/css/codesite.pack.01312008.css" type="text/css" rel="stylesheet">
</link>
@@ -33,6 +45,7 @@
<div id="skipto"> </div>
<div id="langpref">
<!--<a class="dropdown" href="/">English</a> <span>|</span> <a href="/more/">Site Directory</a> -->
+
</div>
<div id="gc-header">
<div id="logo"><a href="http://code.google.com/android/index.html"><img src="http://code.google.com/android/images/logo_android.gif" alt="Android"/></a></div>
@@ -51,6 +64,7 @@
}
</style>
</noscript>
+
<div id="searchForm2" class="searchForm2" style="display:none">
<form id="searchbox_001456098540849067467:6whlsytkdqg" action="http://www.google.com/cse">
<input type="hidden" name="cx" value="001456098540849067467:6whlsytkdqg" />
@@ -59,6 +73,7 @@
<input type="submit" name="sa" value="Search" title="Search"/>
<br/>
<div class="greytext">e.g. "ajax apis" or "open source"</div>
+
</form>
</div>
<!-- end searchForm2 -->
@@ -71,15 +86,18 @@
<div id="codesiteContent">
<a name="gc-topnav-anchor"></a>
<div id="gc-topnav">
+
<h1>Android Platform Development Kit</h1>
<ul class="gc-topnav-tabs">
<li id="sdk_link"> <a href="http://code.google.com/android/index.html" title="Android Software Development Kit">SDK</a> </li>
<li id="docs_link"> <a href="index.html" title="Official Android documentation">Docs</a> </li>
<li id="faq_link"> <a href="http://code.google.com/android/kb/index.html" title="Answers to frequently asked questions about Android">FAQ</a> </li>
+
<li> <a href="http://android-developers.blogspot.com/" title="Official Android blog">Blog</a> </li>
<li> <a href="http://code.google.com/android/groups.html" title="Android developer forum">Group</a> </li>
<li> <a href="http://code.google.com/android/terms.html" title="Android terms of service">Terms</a> </li>
- <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20power_management.html%20v0.3%20-%209%20June%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+ <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20telephony.html%20v0.6%20-%2025%20November%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+
</ul>
</div>
<!-- end gc-topnav -->
@@ -91,19 +109,18 @@
<h1><a href="index.html">Documentation</a></h1>
<ul>
<li> <strong>Introduction</strong>
+
<ul>
<li><a href="system_requirements.html">Device Requirements</a></li>
</ul>
</li>
<li> <strong>Dev Environment Setup</strong>
<ul>
- <li><a href="source_setup_guide.html">Host System Setup</a></li>
- <li><a href="getting_source_code.html">Getting Source Code</a></li>
- <li> <a href="intro_source_code.html">Source Code Overview</a></li>
<li><a href="build_system.html">Build System</a></li>
</ul>
</li>
<li> <strong>Basic Bring up</strong>
+
<ul>
<li><a href="build_new_device.html">Building New Device</a></li>
<li><a href="bring_up.html">Bring up</a></li>
@@ -111,26 +128,39 @@
<li><a href="display_drivers.html">Display Drivers</a></li>
</ul>
</li>
+
<li> <strong>Multimedia</strong>
<ul>
- <li><a href="audio_sub_system.html">Audio Subsystem</a></li>
+ <li><a href="audio_sub_system.html">Audio</a></li>
+ <li><a href="camera.html">Camera</a></li>
</ul>
</li>
<li> <strong>Power Management</strong>
+
<ul>
<li><a href="power_management.html">Power Management</a></li>
</ul>
</li>
+
+ <li> <strong>Networking</strong>
+ <ul>
+ <li><a href="wifi.html">Wi-Fi</a></li>
+ <li><a href="gps.html">GPS</a></li>
+ <li><a href="bluetooth.html">Bluetooth</a></li>
+ </ul>
+ </li>
+
<li> <strong>Telephony</strong>
<ul>
<li><a href="telephony.html">Radio Interface Layer</a></li>
+
</ul>
</li>
<li> <strong>Testing</strong>
<ul>
- <li><a href="instrumentation_framework.html">Instrumentation Framework</a></li>
<li><a href="instrumentation_testing.html">Instrumentation Testing</a></li>
</ul>
+
</li>
</ul>
</li>
@@ -170,7 +200,7 @@
<p>The diagram below illustrates the RIL in the context of Android's Telephony system architecture.</p>
<p><img src="telephony.gif"></p>
-Solid elements represent Android blocks and dashed elements represent partner-specific proprietary blocks.
+Solid elements represent Android blocks and dashed elements represent partner-specific blocks.
<p>The RIL consists of two primary components:</p>
<p><ul>
@@ -393,7 +423,7 @@
pageTracker._trackPageview();
} catch(e) {}
</script>
-<div id="jd-build-id"> v0.3 - 9 June 2008</div>
+<div id="jd-build-id"> v0.6 - 25 November 2008</div>
</div></div></div></body>
</html>
diff --git a/pdk/docs/wifi.html b/pdk/docs/wifi.html
new file mode 100755
index 0000000..df40fb0
--- /dev/null
+++ b/pdk/docs/wifi.html
@@ -0,0 +1,250 @@
+
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
+<title>Android - Porting Guide</title>
+<script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=internal-codesite" type="text/javascript"></script>
+<script src="http://code.google.com/js/jquery.js" type="text/javascript"></script>
+<script type="text/javascript">var _tocPath_ = 'http://code.google.com/android/_toc.ezt';</script>
+<script src="http://code.google.com/js/codesite.pack.01312008.js" type="text/javascript"></script>
+<script language="JavaScript">
+function resizeHeight() {
+ if(document.getElementById && !(document.all)) {
+ height= document.getElementById('doxygen').contentDocument.body.scrollHeight + 20;
+ document.getElementById('doxygen').style.height = height;
+ }
+ else if(document.all) {
+ height= document.frames('doxygen').document.body.scrollHeight + 20;
+ document.all.doxygen.style.height = height;
+ }
+}
+</script>
+<link href="http://code.google.com/css/codesite.pack.01312008.css" type="text/css" rel="stylesheet">
+</link>
+
+<!--[if IE]><link rel="stylesheet" type="text/css" href="/css/iehacks.css" /><![endif]-->
+<script src="http://code.google.com/android/assets/search_autocomplete.js"></script>
+<link rel="stylesheet" type="text/css" href="http://code.google.com/css/semantic_headers.css" />
+<link rel="stylesheet" type="text/css" href="http://code.google.com/android/assets/style.css" />
+<script>
+ jQuery(document).ready(function() {
+ jQuery("pre").addClass("prettyprint");
+ });
+ </script>
+<style type="text/css">
+<!--
+h1,h2,h3 {
+ color: #000000;
+}
+-->
+</style>
+</head>
+<body class="gc-documentation">
+<div id="gc-container">
+<a name="top"></a>
+<div id="skipto"> </div>
+<div id="langpref">
+ <!--<a class="dropdown" href="/">English</a> <span>|</span> <a href="/more/">Site Directory</a> -->
+
+</div>
+<div id="gc-header">
+ <div id="logo"><a href="http://code.google.com/android/index.html"><img src="http://code.google.com/android/images/logo_android.gif" alt="Android"/></a></div>
+ <div id="search" style="inline">
+ <div id="searchForm" class="searchForm" style="height: 44px;">
+ <!--previously form was here-->
+ </div>
+ <!-- end searchForm -->
+ <noscript>
+ <style type="text/css">
+ .searchForm {
+ display : none !important;
+ }
+ .searchForm2 {
+ display : inline !important;
+ }
+ </style>
+ </noscript>
+
+ <div id="searchForm2" class="searchForm2" style="display:none">
+ <form id="searchbox_001456098540849067467:6whlsytkdqg" action="http://www.google.com/cse">
+ <input type="hidden" name="cx" value="001456098540849067467:6whlsytkdqg" />
+ <input type="hidden" name="cof" value="FORID:0" />
+ <input type="text" name="q" maxlength="2048" size="41" autocomplete="off" title="Google Code Search"/>
+ <input type="submit" name="sa" value="Search" title="Search"/>
+ <br/>
+ <div class="greytext">e.g. "ajax apis" or "open source"</div>
+
+ </form>
+ </div>
+ <!-- end searchForm2 -->
+ </div>
+ <!-- end search -->
+</div>
+<!-- end gc-header -->
+<div id="searchControl" class="search-control"></div>
+<!--[if IE]><iframe id="backiFrame" name="backiFrame" src='/dummy.html' style="display:none"></iframe><![endif]-->
+<div id="codesiteContent">
+<a name="gc-topnav-anchor"></a>
+<div id="gc-topnav">
+
+ <h1>Android Platform Development Kit</h1>
+ <ul class="gc-topnav-tabs">
+ <li id="sdk_link"> <a href="http://code.google.com/android/index.html" title="Android Software Development Kit">SDK</a> </li>
+ <li id="docs_link"> <a href="index.html" title="Official Android documentation">Docs</a> </li>
+ <li id="faq_link"> <a href="http://code.google.com/android/kb/index.html" title="Answers to frequently asked questions about Android">FAQ</a> </li>
+
+ <li> <a href="http://android-developers.blogspot.com/" title="Official Android blog">Blog</a> </li>
+ <li> <a href="http://code.google.com/android/groups.html" title="Android developer forum">Group</a> </li>
+ <li> <a href="http://code.google.com/android/terms.html" title="Android terms of service">Terms</a> </li>
+ <li> <a href="mailto:android-pdk-feedback@google.com?subject=PDK%20Feedback&body=(filed%20from:%20wifi.html%20v0.6%20-%2025%20November%202008)%0D%0A%0D%0ASUMMARY:%0D%0A%0D%0A%0D%0A%0D%0ASTEPS%20TO%20REPRODUCE:%0D%0A%0D%0A%0D%0A%0D%0AADDITIONAL%20NOTES:">Report a Problem</a> </li>
+
+ </ul>
+</div>
+<!-- end gc-topnav -->
+<div class="g-section g-tpl-180">
+<a name="gc-toc"></a>
+<div class="g-unit g-first" id="gc-toc">
+ <ul>
+ <li>
+ <h1><a href="index.html">Documentation</a></h1>
+ <ul>
+ <li> <strong>Introduction</strong>
+
+ <ul>
+ <li><a href="system_requirements.html">Device Requirements</a></li>
+ </ul>
+ </li>
+ <li> <strong>Dev Environment Setup</strong>
+ <ul>
+ <li><a href="build_system.html">Build System</a></li>
+ </ul>
+ </li>
+ <li> <strong>Basic Bring up</strong>
+
+ <ul>
+ <li><a href="build_new_device.html">Building New Device</a></li>
+ <li><a href="bring_up.html">Bring up</a></li>
+ <li><a href="keymaps_keyboard_input.html">Keymaps and Keyboard</a></li>
+ <li><a href="display_drivers.html">Display Drivers</a></li>
+ </ul>
+ </li>
+
+ <li> <strong>Multimedia</strong>
+ <ul>
+ <li><a href="audio_sub_system.html">Audio</a></li>
+ <li><a href="camera.html">Camera</a></li>
+ </ul>
+ </li>
+ <li> <strong>Power Management</strong>
+
+ <ul>
+ <li><a href="power_management.html">Power Management</a></li>
+ </ul>
+ </li>
+
+ <li> <strong>Networking</strong>
+ <ul>
+ <li><a href="wifi.html">Wi-Fi</a></li>
+ <li><a href="gps.html">GPS</a></li>
+ <li><a href="bluetooth.html">Bluetooth</a></li>
+ </ul>
+ </li>
+
+ <li> <strong>Telephony</strong>
+ <ul>
+ <li><a href="telephony.html">Radio Interface Layer</a></li>
+
+ </ul>
+ </li>
+ <li> <strong>Testing</strong>
+ <ul>
+ <li><a href="instrumentation_testing.html">Instrumentation Testing</a></li>
+ </ul>
+
+ </li>
+ </ul>
+ </li>
+ </ul>
+</div>
+<a name="gc-pagecontent"></a>
+<div class="g-unit" id="gc-pagecontent">
+<div id="jd-content">
+<div class="jd-descr">
+
+
+<a name="androidWifiTitle"></a><h1>Wi-Fi</h1>
+
+
+
+<a name="toc"/>
+<div style="padding:10px">
+<a href="#androidWifiIntroduction">Introduction</a><br/>
+<a href="#androidWifiBuildingDriver">Building a Wi-Fi Library</a><br/>
+<a href="#androidWifiInterface">Interface</a><br/></div></font></div>
+
+<a name="androidWifiIntroduction"></a><h2>Introduction</h2>
+
+<p>Android uses wpa_supplicant as the platform interface to the Wi-Fi device. Your Wi-Fi driver must be compatible with the standard wpa_supplicant in addition to extensions added to the supplicant (specifically, the "DRIVER" commands described in <code>wifi.h/wifi_command()</code>).</p>
+
+
+<a name="androidWifiBuildingDriver"></a><h2>Building a Wi-Fi Library</h2>
+
+<p>To create a Wi-Fi driver for Android:</p>
+<p><ul>
+<li>create a shared library that implements the interface defined in <code>include/hardware/wifi.h</code>, which also defines the Wi-Fi supplicant.</li>
+<li>Follow the instructions posted at <a href="http://hostap.epitest.fi/wpa_supplicant/">http://hostap.epitest.fi/wpa_supplicant/</a>.</li>
+<li>Place your driver in <code>libs/hardware/wifi/</code></li>
+<li>Test your driver using the command line <code>wpa_cli</code> utilities.</li>
+</ul>
+
+<p>You can find the default implementation in <code>libs/hardware/wifi/wifi.c</code>. If you need to make changes, create a new source file similar to <code>wifi.c</code>, for example, <code>wifi_mywifi.c</code>. </p>
+
+<p>Update the default <code>Android.mk</code> file (<code>libs/hardware/wifi/Android.mk</code>) as shown below.</p>
+<pre class="prettify">
+LOCAL_SHARED_LIBRARIES += libnetutils
+
+ifeq ($(TARGET_DEVICE),acme)
+LOCAL_SRC_FILES += wifi/wifi_mywifi.c
+else
+LOCAL_SRC_FILES += wifi/wifi.c
+endif
+</pre>
+
+
+<a name="androidWifiInterface"></a><h2>Interface</h2>
+
+
+
+<p class="note"><strong>Note</strong>: This document relies on some Doxygen-generated content that appears in an iFrame below. To return to the Doxygen default content for this page, <a href="wifi.html">click here</a>.</p>
+
+
+<iframe onLoad="resizeHeight();" src="wifi_8h.html" scrolling="no" scroll="no" id="doxygen" marginwidth="0" marginheight="0" frameborder="0" style="width:100%;"></iframe>
+
+
+ </div>
+ </div>
+ <!-- end gc-pagecontent -->
+ </div>
+ <!-- end gooey wrapper -->
+ </div>
+ <!-- end codesearchresults -->
+ <div id="gc-footer" dir="ltr">
+ <div class="text"> ©2008 Google<!-- - <a href="/">Code Home</a> - <a href="http://www.google.com/accounts/TOS">Site Terms of Service</a> - <a href="http://www.google.com/privacy.html">Privacy Policy</a> - <a href="/more">Site Directory</a> --></div>
+ </div>
+ <!-- end gc-footer -->
+</div>
+<!-- end gc-containter -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-18071-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+<div id="jd-build-id"> v0.6 - 25 November 2008</div>
+</div></div></div></body>
+</html>
+
diff --git a/pdk/docs/wifi_8h-source.html b/pdk/docs/wifi_8h-source.html
new file mode 100755
index 0000000..806dd79
--- /dev/null
+++ b/pdk/docs/wifi_8h-source.html
@@ -0,0 +1,200 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li class="current"><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+</div>
+<h1>wifi.h</h1><a href="wifi_8h.html">Go to the documentation of this file.</a><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*</span>
+<a name="l00002"></a>00002 <span class="comment"> * Copyright (C) 2008 The Android Open Source Project</span>
+<a name="l00003"></a>00003 <span class="comment"> *</span>
+<a name="l00004"></a>00004 <span class="comment"> * Licensed under the Apache License, Version 2.0 (the "License");</span>
+<a name="l00005"></a>00005 <span class="comment"> * you may not use this file except in compliance with the License.</span>
+<a name="l00006"></a>00006 <span class="comment"> * You may obtain a copy of the License at</span>
+<a name="l00007"></a>00007 <span class="comment"> *</span>
+<a name="l00008"></a>00008 <span class="comment"> * http://www.apache.org/licenses/LICENSE-2.0</span>
+<a name="l00009"></a>00009 <span class="comment"> *</span>
+<a name="l00010"></a>00010 <span class="comment"> * Unless required by applicable law or agreed to in writing, software</span>
+<a name="l00011"></a>00011 <span class="comment"> * distributed under the License is distributed on an "AS IS" BASIS,</span>
+<a name="l00012"></a>00012 <span class="comment"> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span>
+<a name="l00013"></a>00013 <span class="comment"> * See the License for the specific language governing permissions and</span>
+<a name="l00014"></a>00014 <span class="comment"> * limitations under the License.</span>
+<a name="l00015"></a>00015 <span class="comment"> */</span>
+<a name="l00016"></a>00016
+<a name="l00017"></a>00017 <span class="preprocessor">#ifndef _WIFI_H</span>
+<a name="l00018"></a>00018 <span class="preprocessor"></span><span class="preprocessor">#define _WIFI_H</span>
+<a name="l00019"></a>00019 <span class="preprocessor"></span>
+<a name="l00020"></a>00020 <span class="preprocessor">#if __cplusplus</span>
+<a name="l00021"></a>00021 <span class="preprocessor"></span><span class="keyword">extern</span> <span class="stringliteral">"C"</span> {
+<a name="l00022"></a>00022 <span class="preprocessor">#endif</span>
+<a name="l00023"></a>00023 <span class="preprocessor"></span><span class="comment"></span>
+<a name="l00024"></a>00024 <span class="comment">/**</span>
+<a name="l00025"></a>00025 <span class="comment"> * Load the Wi-Fi driver.</span>
+<a name="l00026"></a>00026 <span class="comment"> *</span>
+<a name="l00027"></a>00027 <span class="comment"> * @return 0 on success, < 0 on failure.</span>
+<a name="l00028"></a>00028 <span class="comment"> */</span>
+<a name="l00029"></a>00029 <span class="keywordtype">int</span> <a class="code" href="wifi_8h.html#ef0be2b5d0603acb8e0ab99051969bb7" title="Load the Wi-Fi driver.">wifi_load_driver</a>();
+<a name="l00030"></a>00030 <span class="comment"></span>
+<a name="l00031"></a>00031 <span class="comment">/**</span>
+<a name="l00032"></a>00032 <span class="comment"> * Unload the Wi-Fi driver.</span>
+<a name="l00033"></a>00033 <span class="comment"> *</span>
+<a name="l00034"></a>00034 <span class="comment"> * @return 0 on success, < 0 on failure.</span>
+<a name="l00035"></a>00035 <span class="comment"> */</span>
+<a name="l00036"></a>00036 <span class="keywordtype">int</span> <a class="code" href="wifi_8h.html#a0c054da650a0162e40f327eb05679cb" title="Unload the Wi-Fi driver.">wifi_unload_driver</a>();
+<a name="l00037"></a>00037 <span class="comment"></span>
+<a name="l00038"></a>00038 <span class="comment">/**</span>
+<a name="l00039"></a>00039 <span class="comment"> * Start supplicant.</span>
+<a name="l00040"></a>00040 <span class="comment"> *</span>
+<a name="l00041"></a>00041 <span class="comment"> * @return 0 on success, < 0 on failure.</span>
+<a name="l00042"></a>00042 <span class="comment"> */</span>
+<a name="l00043"></a>00043 <span class="keywordtype">int</span> <a class="code" href="wifi_8h.html#3372e235a7899484912d7f85887e8a47" title="Start supplicant.">wifi_start_supplicant</a>();
+<a name="l00044"></a>00044 <span class="comment"></span>
+<a name="l00045"></a>00045 <span class="comment">/**</span>
+<a name="l00046"></a>00046 <span class="comment"> * Stop supplicant.</span>
+<a name="l00047"></a>00047 <span class="comment"> *</span>
+<a name="l00048"></a>00048 <span class="comment"> * @return 0 on success, < 0 on failure.</span>
+<a name="l00049"></a>00049 <span class="comment"> */</span>
+<a name="l00050"></a>00050 <span class="keywordtype">int</span> <a class="code" href="wifi_8h.html#08b97e58f2909489f1f3d59fb31f2c19" title="Stop supplicant.">wifi_stop_supplicant</a>();
+<a name="l00051"></a>00051 <span class="comment"></span>
+<a name="l00052"></a>00052 <span class="comment">/**</span>
+<a name="l00053"></a>00053 <span class="comment"> * Open a connection to supplicant.</span>
+<a name="l00054"></a>00054 <span class="comment"> *</span>
+<a name="l00055"></a>00055 <span class="comment"> * @return 0 on success, < 0 on failure.</span>
+<a name="l00056"></a>00056 <span class="comment"> */</span>
+<a name="l00057"></a>00057 <span class="keywordtype">int</span> <a class="code" href="wifi_8h.html#d81473c3f314ba581e88bb9f1ae37904" title="Open a connection to supplicant.">wifi_connect_to_supplicant</a>();
+<a name="l00058"></a>00058 <span class="comment"></span>
+<a name="l00059"></a>00059 <span class="comment">/**</span>
+<a name="l00060"></a>00060 <span class="comment"> * Close connection supplicant.</span>
+<a name="l00061"></a>00061 <span class="comment"> *</span>
+<a name="l00062"></a>00062 <span class="comment"> * @return 0 on success, < 0 on failure.</span>
+<a name="l00063"></a>00063 <span class="comment"> */</span>
+<a name="l00064"></a>00064 <span class="keywordtype">void</span> <a class="code" href="wifi_8h.html#a3f8c99b26cfd95e90012cae63ec4826" title="Close connection supplicant.">wifi_close_supplicant_connection</a>();
+<a name="l00065"></a>00065 <span class="comment"></span>
+<a name="l00066"></a>00066 <span class="comment">/**</span>
+<a name="l00067"></a>00067 <span class="comment"> * wifi_wait_for_event() performs a blocking call to </span>
+<a name="l00068"></a>00068 <span class="comment"> * get a Wi-Fi event and returns a string representing </span>
+<a name="l00069"></a>00069 <span class="comment"> * a Wi-Fi event when it occurs.</span>
+<a name="l00070"></a>00070 <span class="comment"> *</span>
+<a name="l00071"></a>00071 <span class="comment"> * @param buf is the buffer that receives the event</span>
+<a name="l00072"></a>00072 <span class="comment"> * @param len is the maximum length of the buffer</span>
+<a name="l00073"></a>00073 <span class="comment"> *</span>
+<a name="l00074"></a>00074 <span class="comment"> * @returns number of bytes in buffer, 0 if no</span>
+<a name="l00075"></a>00075 <span class="comment"> * event (for instance, no connection), and less than 0</span>
+<a name="l00076"></a>00076 <span class="comment"> * if there is an error.</span>
+<a name="l00077"></a>00077 <span class="comment"> */</span>
+<a name="l00078"></a>00078 <span class="keywordtype">int</span> <a class="code" href="wifi_8h.html#656495e1beea1e39a144cdff776cdb96" title="wifi_wait_for_event() performs a blocking call to get a Wi-Fi event and returns a...">wifi_wait_for_event</a>(<span class="keywordtype">char</span> *buf, <span class="keywordtype">size_t</span> len);
+<a name="l00079"></a>00079 <span class="comment"></span>
+<a name="l00080"></a>00080 <span class="comment">/**</span>
+<a name="l00081"></a>00081 <span class="comment"> * wifi_command() issues a command to the Wi-Fi driver.</span>
+<a name="l00082"></a>00082 <span class="comment"> *</span>
+<a name="l00083"></a>00083 <span class="comment"> * Android extends the standard commands listed at </span>
+<a name="l00084"></a>00084 <span class="comment"> * /link http://hostap.epitest.fi/wpa_supplicant/devel/ctrl_iface_page.html </span>
+<a name="l00085"></a>00085 <span class="comment"> * to include support for sending commands to the driver:</span>
+<a name="l00086"></a>00086 <span class="comment"> *</span>
+<a name="l00087"></a>00087 <span class="comment"> * <table border="2" cellspacing="2" cellpadding="2"></span>
+<a name="l00088"></a>00088 <span class="comment"> * <tr></span>
+<a name="l00089"></a>00089 <span class="comment"> * <td><strong>Command / Command summary</strong></td></span>
+<a name="l00090"></a>00090 <span class="comment"> * <td><strong>Form of Response</strong></td></span>
+<a name="l00091"></a>00091 <span class="comment"> * <td><strong>Processing</strong></td></span>
+<a name="l00092"></a>00092 <span class="comment"> * </tr></span>
+<a name="l00093"></a>00093 <span class="comment"> * <tr></span>
+<a name="l00094"></a>00094 <span class="comment"> * <td>DRIVER START<BR>&nbsp;&nbsp;Turn on Wi-Fi Hardware</td></span>
+<a name="l00095"></a>00095 <span class="comment"> * <td>OK if successful</td></span>
+<a name="l00096"></a>00096 <span class="comment"> * <td>OK ? true : false</td></span>
+<a name="l00097"></a>00097 <span class="comment"> * </tr></span>
+<a name="l00098"></a>00098 <span class="comment"> * <tr></span>
+<a name="l00099"></a>00099 <span class="comment"> * <td>DRIVER STOP<BR>&nbsp;&nbsp;Turn off Wi-Fi hardware</td></span>
+<a name="l00100"></a>00100 <span class="comment"> * <td>OK if successful</td></span>
+<a name="l00101"></a>00101 <span class="comment"> * <td>OK ? true : false</td></span>
+<a name="l00102"></a>00102 <span class="comment"> * </tr></span>
+<a name="l00103"></a>00103 <span class="comment"> * <tr></span>
+<a name="l00104"></a>00104 <span class="comment"> * <td>DRIVER RSSI<BR>&nbsp;&nbsp;Return received signal strength indicator in -db for current AP</td></span>
+<a name="l00105"></a>00105 <span class="comment"> * <td>&lt;ssid&gt; Rssi xx</td></span>
+<a name="l00106"></a>00106 <span class="comment"> * <td>%*s %*s %d", &rssi</td></span>
+<a name="l00107"></a>00107 <span class="comment"> * </tr></span>
+<a name="l00108"></a>00108 <span class="comment"> * <tr></span>
+<a name="l00109"></a>00109 <span class="comment"> * <td>DRIVER LINKSPEED<BR>&nbsp;&nbsp;Return link speed in MBPS</td></span>
+<a name="l00110"></a>00110 <span class="comment"> * <td>LinkSpeed xx</td></span>
+<a name="l00111"></a>00111 <span class="comment"> * <td>%*s %d", &linkspd</td></span>
+<a name="l00112"></a>00112 <span class="comment"> * </tr></span>
+<a name="l00113"></a>00113 <span class="comment"> * <tr></span>
+<a name="l00114"></a>00114 <span class="comment"> * <td>DRIVER MACADDR<BR>&nbsp;&nbsp;Return mac address of the station</td></span>
+<a name="l00115"></a>00115 <span class="comment"> * <td>Macaddr = xx.xx.xx.xx.xx.xx</td></span>
+<a name="l00116"></a>00116 <span class="comment"> * <td>"%*s = %s", &macadr</td></span>
+<a name="l00117"></a>00117 <span class="comment"> * </tr></span>
+<a name="l00118"></a>00118 <span class="comment"> * <tr></span>
+<a name="l00119"></a>00119 <span class="comment"> * <td>DRIVER SCAN-ACTIVE<BR>&nbsp;&nbsp;Set scan type to active</td></span>
+<a name="l00120"></a>00120 <span class="comment"> * <td>"OK" if successful</td></span>
+<a name="l00121"></a>00121 <span class="comment"> * <td>"OK" ? true : false</td></span>
+<a name="l00122"></a>00122 <span class="comment"> * </tr></span>
+<a name="l00123"></a>00123 <span class="comment"> * <tr></span>
+<a name="l00124"></a>00124 <span class="comment"> * <td>DRIVER SCAN-PASSIVE<BR>&nbsp;&nbsp;Set scan type to passive</td></span>
+<a name="l00125"></a>00125 <span class="comment"> * <td>"OK" if successful</td></span>
+<a name="l00126"></a>00126 <span class="comment"> * <td>"OK" ? true : false</td></span>
+<a name="l00127"></a>00127 <span class="comment"> * </tr></span>
+<a name="l00128"></a>00128 <span class="comment"> * </table></span>
+<a name="l00129"></a>00129 <span class="comment"> *</span>
+<a name="l00130"></a>00130 <span class="comment"> * See libs/android_runtime/android_net_wifi_Wifi.cpp for more information</span>
+<a name="l00131"></a>00131 <span class="comment"> * describing how these and other commands are invoked.</span>
+<a name="l00132"></a>00132 <span class="comment"> *</span>
+<a name="l00133"></a>00133 <span class="comment"> * @param command is the string command</span>
+<a name="l00134"></a>00134 <span class="comment"> * @param reply is a buffer to receive a reply string</span>
+<a name="l00135"></a>00135 <span class="comment"> * @param reply_len on entry, this is the maximum length of</span>
+<a name="l00136"></a>00136 <span class="comment"> * the reply buffer. On exit, the number of</span>
+<a name="l00137"></a>00137 <span class="comment"> * bytes in the reply buffer.</span>
+<a name="l00138"></a>00138 <span class="comment"> *</span>
+<a name="l00139"></a>00139 <span class="comment"> * @return 0 if successful, < 0 if an error.</span>
+<a name="l00140"></a>00140 <span class="comment"> */</span>
+<a name="l00141"></a>00141 <span class="keywordtype">int</span> <a class="code" href="wifi_8h.html#b84f92e035b7bc6a5d669b3738c93e32" title="wifi_command() issues a command to the Wi-Fi driver.">wifi_command</a>(<span class="keyword">const</span> <span class="keywordtype">char</span> *command, <span class="keywordtype">char</span> *reply, <span class="keywordtype">size_t</span> *reply_len);
+<a name="l00142"></a>00142 <span class="comment"></span>
+<a name="l00143"></a>00143 <span class="comment">/**</span>
+<a name="l00144"></a>00144 <span class="comment"> * do_dhcp_request() issues a dhcp request and returns the acquired</span>
+<a name="l00145"></a>00145 <span class="comment"> * information. </span>
+<a name="l00146"></a>00146 <span class="comment"> * </span>
+<a name="l00147"></a>00147 <span class="comment"> * All IPV4 addresses/mask are in network byte order.</span>
+<a name="l00148"></a>00148 <span class="comment"> *</span>
+<a name="l00149"></a>00149 <span class="comment"> * @param ipaddr return the assigned IPV4 address</span>
+<a name="l00150"></a>00150 <span class="comment"> * @param gateway return the gateway being used</span>
+<a name="l00151"></a>00151 <span class="comment"> * @param mask return the IPV4 mask</span>
+<a name="l00152"></a>00152 <span class="comment"> * @param dns1 return the IPV4 address of a DNS server</span>
+<a name="l00153"></a>00153 <span class="comment"> * @param dns2 return the IPV4 address of a DNS server</span>
+<a name="l00154"></a>00154 <span class="comment"> * @param server return the IPV4 address of DHCP server</span>
+<a name="l00155"></a>00155 <span class="comment"> * @param lease return the length of lease in seconds.</span>
+<a name="l00156"></a>00156 <span class="comment"> *</span>
+<a name="l00157"></a>00157 <span class="comment"> * @return 0 if successful, < 0 if error.</span>
+<a name="l00158"></a>00158 <span class="comment"> */</span>
+<a name="l00159"></a>00159 <span class="keywordtype">int</span> <a class="code" href="wifi_8h.html#c6876a5403aaeee922d000043a47b25a" title="do_dhcp_request() issues a dhcp request and returns the acquired information.">do_dhcp_request</a>(<span class="keywordtype">int</span> *ipaddr, <span class="keywordtype">int</span> *gateway, <span class="keywordtype">int</span> *mask,
+<a name="l00160"></a>00160 <span class="keywordtype">int</span> *dns1, <span class="keywordtype">int</span> *dns2, <span class="keywordtype">int</span> *server, <span class="keywordtype">int</span> *lease);
+<a name="l00161"></a>00161 <span class="comment"></span>
+<a name="l00162"></a>00162 <span class="comment">/**</span>
+<a name="l00163"></a>00163 <span class="comment"> * Return the error string of the last do_dhcp_request().</span>
+<a name="l00164"></a>00164 <span class="comment"> */</span>
+<a name="l00165"></a>00165 <span class="keyword">const</span> <span class="keywordtype">char</span> *<a class="code" href="wifi_8h.html#8f25ea8ec313efb45affe65fd7c108ee" title="Return the error string of the last do_dhcp_request().">get_dhcp_error_string</a>();
+<a name="l00166"></a>00166
+<a name="l00167"></a>00167 <span class="preprocessor">#if __cplusplus</span>
+<a name="l00168"></a>00168 <span class="preprocessor"></span>}; <span class="comment">// extern "C"</span>
+<a name="l00169"></a>00169 <span class="preprocessor">#endif</span>
+<a name="l00170"></a>00170 <span class="preprocessor"></span>
+<a name="l00171"></a>00171 <span class="preprocessor">#endif // _WIFI_H</span>
+</pre></div></div>
+</body>
+</html>
diff --git a/pdk/docs/wifi_8h.html b/pdk/docs/wifi_8h.html
new file mode 100755
index 0000000..c8285d0
--- /dev/null
+++ b/pdk/docs/wifi_8h.html
@@ -0,0 +1,405 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Doxygen-Generated Content</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<style type="text/css">
+<!--
+.navigation {
+ display: none;
+}
+-->
+</style>
+</head>
+<body>
+<!-- Generated by Doxygen 1.5.6 -->
+<div class="navigation" id="top">
+ <div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main Page</span></a></li>
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
+ <li><a href="annotated.html"><span>Data Structures</span></a></li>
+ <li class="current"><a href="files.html"><span>Files</span></a></li>
+ </ul>
+ </div>
+</div>
+<div class="contents">
+<h1>wifi.h File Reference</h1>
+<p>
+<a href="wifi_8h-source.html">Go to the source code of this file.</a><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int </td><td class="memItemRight" valign="bottom"><a class="el" href="wifi_8h.html#ef0be2b5d0603acb8e0ab99051969bb7">wifi_load_driver</a> ()</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Load the Wi-Fi driver. <a href="#ef0be2b5d0603acb8e0ab99051969bb7"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int </td><td class="memItemRight" valign="bottom"><a class="el" href="wifi_8h.html#a0c054da650a0162e40f327eb05679cb">wifi_unload_driver</a> ()</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Unload the Wi-Fi driver. <a href="#a0c054da650a0162e40f327eb05679cb"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int </td><td class="memItemRight" valign="bottom"><a class="el" href="wifi_8h.html#3372e235a7899484912d7f85887e8a47">wifi_start_supplicant</a> ()</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Start supplicant. <a href="#3372e235a7899484912d7f85887e8a47"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int </td><td class="memItemRight" valign="bottom"><a class="el" href="wifi_8h.html#08b97e58f2909489f1f3d59fb31f2c19">wifi_stop_supplicant</a> ()</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Stop supplicant. <a href="#08b97e58f2909489f1f3d59fb31f2c19"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int </td><td class="memItemRight" valign="bottom"><a class="el" href="wifi_8h.html#d81473c3f314ba581e88bb9f1ae37904">wifi_connect_to_supplicant</a> ()</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Open a connection to supplicant. <a href="#d81473c3f314ba581e88bb9f1ae37904"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="wifi_8h.html#a3f8c99b26cfd95e90012cae63ec4826">wifi_close_supplicant_connection</a> ()</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Close connection supplicant. <a href="#a3f8c99b26cfd95e90012cae63ec4826"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int </td><td class="memItemRight" valign="bottom"><a class="el" href="wifi_8h.html#656495e1beea1e39a144cdff776cdb96">wifi_wait_for_event</a> (char *buf, size_t len)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight"><a class="el" href="wifi_8h.html#656495e1beea1e39a144cdff776cdb96" title="wifi_wait_for_event() performs a blocking call to get a Wi-Fi event and returns a...">wifi_wait_for_event()</a> performs a blocking call to get a Wi-Fi event and returns a string representing a Wi-Fi event when it occurs. <a href="#656495e1beea1e39a144cdff776cdb96"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int </td><td class="memItemRight" valign="bottom"><a class="el" href="wifi_8h.html#b84f92e035b7bc6a5d669b3738c93e32">wifi_command</a> (const char *command, char *reply, size_t *reply_len)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight"><a class="el" href="wifi_8h.html#b84f92e035b7bc6a5d669b3738c93e32" title="wifi_command() issues a command to the Wi-Fi driver.">wifi_command()</a> issues a command to the Wi-Fi driver. <a href="#b84f92e035b7bc6a5d669b3738c93e32"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int </td><td class="memItemRight" valign="bottom"><a class="el" href="wifi_8h.html#c6876a5403aaeee922d000043a47b25a">do_dhcp_request</a> (int *ipaddr, int *gateway, int *mask, int *dns1, int *dns2, int *server, int *lease)</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight"><a class="el" href="wifi_8h.html#c6876a5403aaeee922d000043a47b25a" title="do_dhcp_request() issues a dhcp request and returns the acquired information.">do_dhcp_request()</a> issues a dhcp request and returns the acquired information. <a href="#c6876a5403aaeee922d000043a47b25a"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">const char * </td><td class="memItemRight" valign="bottom"><a class="el" href="wifi_8h.html#8f25ea8ec313efb45affe65fd7c108ee">get_dhcp_error_string</a> ()</td></tr>
+
+<tr><td class="mdescLeft"> </td><td class="mdescRight">Return the error string of the last <a class="el" href="wifi_8h.html#c6876a5403aaeee922d000043a47b25a" title="do_dhcp_request() issues a dhcp request and returns the acquired information.">do_dhcp_request()</a>. <a href="#8f25ea8ec313efb45affe65fd7c108ee"></a><br></td></tr>
+</table>
+<hr><h2>Function Documentation</h2>
+<a class="anchor" name="c6876a5403aaeee922d000043a47b25a"></a><!-- doxytag: member="wifi.h::do_dhcp_request" ref="c6876a5403aaeee922d000043a47b25a" args="(int *ipaddr, int *gateway, int *mask, int *dns1, int *dns2, int *server, int *lease)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int do_dhcp_request </td>
+ <td>(</td>
+ <td class="paramtype">int * </td>
+ <td class="paramname"> <em>ipaddr</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int * </td>
+ <td class="paramname"> <em>gateway</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int * </td>
+ <td class="paramname"> <em>mask</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int * </td>
+ <td class="paramname"> <em>dns1</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int * </td>
+ <td class="paramname"> <em>dns2</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int * </td>
+ <td class="paramname"> <em>server</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int * </td>
+ <td class="paramname"> <em>lease</em></td><td> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+<a class="el" href="wifi_8h.html#c6876a5403aaeee922d000043a47b25a" title="do_dhcp_request() issues a dhcp request and returns the acquired information.">do_dhcp_request()</a> issues a dhcp request and returns the acquired information.
+<p>
+All IPV4 addresses/mask are in network byte order.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ipaddr</em> </td><td>return the assigned IPV4 address </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>gateway</em> </td><td>return the gateway being used </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>mask</em> </td><td>return the IPV4 mask </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>dns1</em> </td><td>return the IPV4 address of a DNS server </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>dns2</em> </td><td>return the IPV4 address of a DNS server </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>server</em> </td><td>return the IPV4 address of DHCP server </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>lease</em> </td><td>return the length of lease in seconds.</td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 if successful, < 0 if error. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="8f25ea8ec313efb45affe65fd7c108ee"></a><!-- doxytag: member="wifi.h::get_dhcp_error_string" ref="8f25ea8ec313efb45affe65fd7c108ee" args="()" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">const char* get_dhcp_error_string </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Return the error string of the last <a class="el" href="wifi_8h.html#c6876a5403aaeee922d000043a47b25a" title="do_dhcp_request() issues a dhcp request and returns the acquired information.">do_dhcp_request()</a>.
+<p>
+
+</div>
+</div><p>
+<a class="anchor" name="a3f8c99b26cfd95e90012cae63ec4826"></a><!-- doxytag: member="wifi.h::wifi_close_supplicant_connection" ref="a3f8c99b26cfd95e90012cae63ec4826" args="()" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">void wifi_close_supplicant_connection </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Close connection supplicant.
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 on success, < 0 on failure. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="b84f92e035b7bc6a5d669b3738c93e32"></a><!-- doxytag: member="wifi.h::wifi_command" ref="b84f92e035b7bc6a5d669b3738c93e32" args="(const char *command, char *reply, size_t *reply_len)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int wifi_command </td>
+ <td>(</td>
+ <td class="paramtype">const char * </td>
+ <td class="paramname"> <em>command</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">char * </td>
+ <td class="paramname"> <em>reply</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t * </td>
+ <td class="paramname"> <em>reply_len</em></td><td> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+<a class="el" href="wifi_8h.html#b84f92e035b7bc6a5d669b3738c93e32" title="wifi_command() issues a command to the Wi-Fi driver.">wifi_command()</a> issues a command to the Wi-Fi driver.
+<p>
+Android extends the standard commands listed at /link <a href="http://hostap.epitest.fi/wpa_supplicant/devel/ctrl_iface_page.html">http://hostap.epitest.fi/wpa_supplicant/devel/ctrl_iface_page.html</a> to include support for sending commands to the driver:<p>
+<table border="2" cellspacing="2" cellpadding="2">
+<tr>
+<td><b>Command / Command summary</b> </td><td><b>Form of Response</b> </td><td><b>Processing</b> </td></tr>
+<tr>
+<td>DRIVER START<br>
+ Turn on Wi-Fi Hardware </td><td>OK if successful </td><td>OK ? true : false </td></tr>
+<tr>
+<td>DRIVER STOP<br>
+ Turn off Wi-Fi hardware </td><td>OK if successful </td><td>OK ? true : false </td></tr>
+<tr>
+<td>DRIVER RSSI<br>
+ Return received signal strength indicator in -db for current AP </td><td><ssid> Rssi xx </td><td>*s *s d", &rssi </td></tr>
+<tr>
+<td>DRIVER LINKSPEED<br>
+ Return link speed in MBPS </td><td>LinkSpeed xx </td><td>*s d", &linkspd </td></tr>
+<tr>
+<td>DRIVER MACADDR<br>
+ Return mac address of the station </td><td>Macaddr = xx.xx.xx.xx.xx.xx </td><td>"%*s = %s", &macadr </td></tr>
+<tr>
+<td>DRIVER SCAN-ACTIVE<br>
+ Set scan type to active </td><td>"OK" if successful </td><td>"OK" ? true : false </td></tr>
+<tr>
+<td>DRIVER SCAN-PASSIVE<br>
+ Set scan type to passive </td><td>"OK" if successful </td><td>"OK" ? true : false </td></tr>
+</table>
+<p>
+See libs/android_runtime/android_net_wifi_Wifi.cpp for more information describing how these and other commands are invoked.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>command</em> </td><td>is the string command </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>reply</em> </td><td>is a buffer to receive a reply string </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>reply_len</em> </td><td>on entry, this is the maximum length of the reply buffer. On exit, the number of bytes in the reply buffer.</td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 if successful, < 0 if an error. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="d81473c3f314ba581e88bb9f1ae37904"></a><!-- doxytag: member="wifi.h::wifi_connect_to_supplicant" ref="d81473c3f314ba581e88bb9f1ae37904" args="()" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int wifi_connect_to_supplicant </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Open a connection to supplicant.
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 on success, < 0 on failure. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ef0be2b5d0603acb8e0ab99051969bb7"></a><!-- doxytag: member="wifi.h::wifi_load_driver" ref="ef0be2b5d0603acb8e0ab99051969bb7" args="()" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int wifi_load_driver </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Load the Wi-Fi driver.
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 on success, < 0 on failure. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="3372e235a7899484912d7f85887e8a47"></a><!-- doxytag: member="wifi.h::wifi_start_supplicant" ref="3372e235a7899484912d7f85887e8a47" args="()" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int wifi_start_supplicant </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Start supplicant.
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 on success, < 0 on failure. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="08b97e58f2909489f1f3d59fb31f2c19"></a><!-- doxytag: member="wifi.h::wifi_stop_supplicant" ref="08b97e58f2909489f1f3d59fb31f2c19" args="()" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int wifi_stop_supplicant </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Stop supplicant.
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 on success, < 0 on failure. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="a0c054da650a0162e40f327eb05679cb"></a><!-- doxytag: member="wifi.h::wifi_unload_driver" ref="a0c054da650a0162e40f327eb05679cb" args="()" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int wifi_unload_driver </td>
+ <td>(</td>
+ <td class="paramname"> </td>
+ <td> ) </td>
+ <td></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Unload the Wi-Fi driver.
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 on success, < 0 on failure. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="656495e1beea1e39a144cdff776cdb96"></a><!-- doxytag: member="wifi.h::wifi_wait_for_event" ref="656495e1beea1e39a144cdff776cdb96" args="(char *buf, size_t len)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int wifi_wait_for_event </td>
+ <td>(</td>
+ <td class="paramtype">char * </td>
+ <td class="paramname"> <em>buf</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"> <em>len</em></td><td> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+<a class="el" href="wifi_8h.html#656495e1beea1e39a144cdff776cdb96" title="wifi_wait_for_event() performs a blocking call to get a Wi-Fi event and returns a...">wifi_wait_for_event()</a> performs a blocking call to get a Wi-Fi event and returns a string representing a Wi-Fi event when it occurs.
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>buf</em> </td><td>is the buffer that receives the event </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>len</em> </td><td>is the maximum length of the buffer</td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>number of bytes in buffer, 0 if no event (for instance, no connection), and less than 0 if there is an error. </dd></dl>
+
+</div>
+</div><p>
+</div>
+</body>
+</html>
diff --git a/pdk/ndk/Ndk.mk b/pdk/ndk/Ndk.mk
index f18e5a8..d5d0b1b 100644
--- a/pdk/ndk/Ndk.mk
+++ b/pdk/ndk/Ndk.mk
@@ -18,10 +18,6 @@
# Assembled using the generic build by default.
# (set in device/config/product_config.make)
-# NOTE: gcc source is in a separate perforce tree which must be checked out to
-# the same directory that the device code is checked out to; so that gcc can be
-# copied from ../toolchain/compiler/gcc-4.2.1
-
# A macro to make rules to copy all newer files in a directory tree matching an
# optional find filter and add the files to a list variable for dependencies.
# Designed after copy_headers.make: Create a rule to copy each file;
@@ -40,24 +36,41 @@
endef
#-------------------------------------------------------------------------------
-# Install all the files needed to build the ndk (both with and without source)
-# We make three sets of trees:
-# Common files used in both versions of the ndk
-# Files used in the standard ndk (no source files included)
-# Files used in the ndk-src (includes source files)
-# We do this as some partners want to recompile our libraries for optimization
+# Install all the files needed to build the ndk.
+# We build three versions of the NDK
+# (1) The full version, with source.
+# (2) The full version, without source.
+# (3) A JNI-only version, with source.
+#
+# We make five sets of trees:
+# (A) Common files used in all versions of the NDK
+# (B) Common files used in the full versions of the NDK
+# (C) Files used in the standard ndk (no source files included)
+# (D) Files used in both the JNI-only and full-with-source version
+# (E) Files used in just the full-with-source version
+#
+# Each NDK version is created by combining the appropriate trees:
+#
+# (A) (B) (C) (D) (E)
+# (1) yes yes yes yes
+# (2) yes yes yes
+# (3) yes yes
+#
+# Source is provided for partners who want to recompile our libraries for optimization.
+# The JNI-only version is provided for partners that want to create shared
+# libraries that can be packaged with APK files and called from Java code.
LOCAL_PATH := $(my-dir)
# Source trees for the ndk
-sample_src_dir := $(LOCAL_PATH)/sample
+samples_src_dir := $(LOCAL_PATH)/samples
+sample_src_dir := $(samples_src_dir)/sample
+samplejni_src_dir := $(samples_src_dir)/samplejni
config_src_dir := $(LOCAL_PATH)/config
kernel_common_src_dir := $(KERNEL_HEADERS_COMMON)
kernel_arch_src_dir := $(KERNEL_HEADERS_ARCH)
-bionic_src_dir := system/bionic
-libm_src_dir := system/libm
-libstdcpp_src_dir := system/libstdc++
-gcc_src_dir := ../toolchain/compiler/gcc-4.2.1
+bionic_src_dir := bionic
+jni_src_dir := $(JNI_H_INCLUDE)
# Workspace directory
ndk_intermediates := $(call intermediates-dir-for,PACKAGING,ndk)
@@ -65,24 +78,26 @@
# Common destination trees for the ndk
ndk_common_tree := $(ndk_intermediates)/common
ndk_common_dest_dir := $(ndk_common_tree)/ndk
-sample_dest_dir := $(ndk_common_dest_dir)/sample
+samplejni_dest_dir := $(ndk_common_dest_dir)/samples/samplejni
config_dest_dir := $(ndk_common_dest_dir)/config
kernel_dest_dir := $(ndk_common_dest_dir)/include/kernel/include
gcc_dest_dir := $(ndk_common_dest_dir)/toolchain
+jni_dest_dir := $(ndk_common_dest_dir)/include/nativehelper
+
+# Common-full destination trees for the ndk
+ndk_common_full_tree := $(ndk_intermediates)/common_full
+ndk_common_full_dest_dir := $(ndk_common_full_tree)/ndk
+sample_dest_dir := $(ndk_common_full_dest_dir)/samples/sample
# Destination trees without source for the standard ndk (without source)
ndk_no_src_tree := $(ndk_intermediates)/no_src
ndk_no_src_dest_dir := $(ndk_no_src_tree)/ndk
bionic_no_src_dest_dir := $(ndk_no_src_dest_dir)/include/bionic
-libm_no_src_dest_dir := $(ndk_no_src_dest_dir)/include/libm
-libstdcpp_no_src_dest_dir := $(ndk_no_src_dest_dir)/include/libstdc++
# Destination trees including source for the ndk with source
ndk_src_tree := $(ndk_intermediates)/with_src
ndk_src_dest_dir := $(ndk_src_tree)/ndk
bionic_src_dest_dir := $(ndk_src_dest_dir)/include/bionic
-libm_src_dest_dir := $(ndk_src_dest_dir)/include/libm
-libstdcpp_src_dest_dir := $(ndk_src_dest_dir)/include/libstdc++
# Destinations of all common files (not picked up by tree rules below)
ndk_common_dest_files := $(ndk_common_dest_dir)/README \
@@ -91,56 +106,64 @@
$(ndk_common_dest_dir)/lib/crtbegin_dynamic.o \
$(ndk_common_dest_dir)/lib/crtend_android.o \
$(ndk_common_dest_dir)/lib/libc.so \
- $(ndk_common_dest_dir)/lib/libdl.so \
- $(ndk_common_dest_dir)/lib/libm.so \
- $(ndk_common_dest_dir)/lib/libstdc++.so
+ $(ndk_common_dest_dir)/lib/libm.so
+
+# Destinations of files used by the full, non-jni-only configurations
+ndk_common_full_dest_files := \
+ $(ndk_common_full_dest_dir)/lib/libdl.so \
+ $(ndk_common_full_dest_dir)/lib/libstdc++.so
# Install common files outside common trees
$(ndk_common_dest_dir)/README: $(LOCAL_PATH)/README | $(ACP)
@echo "NDK README: from $? to $@"
$(copy-file-to-target)
-$(ndk_common_dest_dir)/config/armelf.x: config/armelf.x | $(ACP)
+$(ndk_common_dest_dir)/config/armelf.x: $(BUILD_SYSTEM)/armelf.x | $(ACP)
@echo "NDK config: $@"
$(copy-file-to-target)
-$(ndk_common_dest_dir)/config/armelflib.x: config/armelflib.x | $(ACP)
+$(ndk_common_dest_dir)/config/armelflib.x: $(BUILD_SYSTEM)/armelflib.x | $(ACP)
@echo "NDK config: $@"
$(copy-file-to-target)
$(ndk_common_dest_dir)/lib/%: $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/% | $(ACP)
@echo "NDK lib: $@"
$(copy-file-to-target)
-# (TODO): libandroid_rumtime libnativehelper
+
+# Install common_full files outside common trees
+$(ndk_common_full_dest_dir)/lib/%: $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/% | $(ACP)
+ @echo "NDK lib full: $@"
+ $(copy-file-to-target)
# Install files in common trees
listvar := ndk_common_dest_files
-$(call define-tree-copy-rules,$(sample_src_dir),$(sample_dest_dir),$(listvar))
+$(call define-tree-copy-rules,$(samplejni_src_dir),$(samplejni_dest_dir),$(listvar))
$(call define-tree-copy-rules,$(config_src_dir),$(config_dest_dir),$(listvar))
$(call define-tree-copy-rules,$(kernel_common_src_dir),$(kernel_dest_dir),$(listvar))
$(call define-tree-copy-rules,$(kernel_arch_src_dir),$(kernel_dest_dir),$(listvar))
-$(call define-tree-copy-rules,$(gcc_src_dir),$(gcc_dest_dir),$(listvar))
-# TODO: jni
-# TODO: gdb
+$(call define-tree-copy-rules,$(jni_src_dir),$(jni_dest_dir),$(listvar), -name jni.h)
+
+# Install files common to the full builds but not the JNI build
+listvar := ndk_common_full_dest_files
+$(call define-tree-copy-rules,$(sample_src_dir),$(sample_dest_dir),$(listvar))
# Install files without sources
listvar := ndk_no_src_dest_files
$(call define-tree-copy-rules,$(bionic_src_dir),$(bionic_no_src_dest_dir),$(listvar),-name '*.h')
-$(call define-tree-copy-rules,$(libm_src_dir),$(libm_no_src_dest_dir),$(listvar),-name '*.h')
-# Pull out files from only the include directory in libstdc++
-$(call define-tree-copy-rules,$(libstdcpp_src_dir),$(libstdcpp_no_src_dest_dir),$(listvar),-regex '.*/include/.*')
# Install files including sources
listvar := ndk_with_src_dest_files
$(call define-tree-copy-rules,$(bionic_src_dir),$(bionic_src_dest_dir),$(listvar))
-$(call define-tree-copy-rules,$(libm_src_dir),$(libm_src_dest_dir),$(listvar))
-$(call define-tree-copy-rules,$(libstdcpp_src_dir),$(libstdcpp_src_dest_dir),$(listvar))
+
#-------------------------------------------------------------------------------
-# Create the two versions of the ndk (with and without source)
+# Create the multiple versions of the ndk:
+# ndk_no_src all files without source
+# ndk_with_source all files with source
+# ndk_jni_with_source just files for building JNI shared libraries with source.
# Name the tar files
-name := android_ndk-$(REQUESTED_PRODUCT)
+name := android_ndk-$(TARGET_PRODUCT)
ifeq ($(TARGET_BUILD_TYPE),debug)
name := $(name)_debug
endif
@@ -149,16 +172,20 @@
ndk_tarfile_zipped := $(ndk_tarfile).gz
ndk_with_src_tarfile := $(ndk_intermediates)/$(name)-src.tar
ndk_with_src_tarfile_zipped := $(ndk_with_src_tarfile).gz
+ndk_jni_with_src_tarfile := $(ndk_intermediates)/$(name)-jni-src.tar
+ndk_jni_with_src_tarfile_zipped := $(ndk_jni_with_src_tarfile).gz
-.PHONY: ndk ndk_with_src ndk_no_src ndk_debug
+.PHONY: ndk ndk_with_src ndk_no_src ndk_jni_with_src ndk_debug
-ndk: ndk_no_src ndk_with_src
+ndk: ndk_no_src ndk_with_src ndk_jni_with_src
ndk_no_src: $(ndk_tarfile_zipped)
ndk_with_src: $(ndk_with_src_tarfile_zipped)
+ndk_jni_with_src: $(ndk_jni_with_src_tarfile_zipped)
# Put the ndk zip files in the distribution directory
$(call dist-for-goals,pdk,$(ndk_tarfile_zipped))
$(call dist-for-goals,pdk,$(ndk_with_src_tarfile_zipped))
+$(call dist-for-goals,pdk,$(ndk_jni_with_src_tarfile_zipped))
# zip up tar files
%.tar.gz: %.tar
@@ -166,15 +193,25 @@
$(hide) gzip -cf $< > $@
# tar up the files without our sources to make the ndk.
-$(ndk_tarfile): $(ndk_common_dest_files) $(ndk_no_src_dest_files)
+$(ndk_tarfile): $(ndk_common_dest_files) $(ndk_common_full_dest_files) $(ndk_no_src_dest_files)
@echo "NDK: $@"
@mkdir -p $(dir $@)
@rm -f $@
$(hide) tar rf $@ -C $(ndk_common_tree) ndk
+ $(hide) tar rf $@ -C $(ndk_common_full_tree) ndk
$(hide) tar rf $@ -C $(ndk_no_src_tree) ndk
# tar up the full sources to make the ndk with sources.
-$(ndk_with_src_tarfile): $(ndk_common_dest_files) $(ndk_with_src_dest_files)
+$(ndk_with_src_tarfile): $(ndk_common_dest_files) $(ndk_common_full_dest_files) $(ndk_with_src_dest_files) $(ndk_full_with_src_dest_files)
+ @echo "NDK: $@"
+ @mkdir -p $(dir $@)
+ @rm -f $@
+ $(hide) tar rf $@ -C $(ndk_common_tree) ndk
+ $(hide) tar rf $@ -C $(ndk_common_full_tree) ndk
+ $(hide) tar rf $@ -C $(ndk_src_tree) ndk
+
+# tar up the sources to make the ndk with JNI support.
+$(ndk_jni_with_src_tarfile): $(ndk_common_dest_files) $(ndk_with_src_dest_files)
@echo "NDK: $@"
@mkdir -p $(dir $@)
@rm -f $@
@@ -184,9 +221,12 @@
# Debugging reporting can go here, add it as a target to get output.
ndk_debug: ndk
@echo "You are here: $@"
- @echo "ndk_with_src tar file: $(ndk_with_src_tarfile_zipped)"
@echo "ndk tar file: $(ndk_tarfile_zipped)"
- @echo "ndk_with_src files: $(ndk_with_src_dest_files)"
+ @echo "ndk_with_src tar file: $(ndk_with_src_tarfile_zipped)"
+ @echo "ndk_jni_with_src tar file: $(ndk_jni_with_src_tarfile_zipped)"
@echo "ndk_files: $(ndk_no_src_dest_files)"
+ @echo "ndk_with_src files: $(ndk_with_src_dest_files)"
+ @echo "ndk_full_with_src files: $(ndk_full_with_src_dest_files)"
@echo "ndk_common_files: $(ndk_common_dest_files)"
+ @echo "ndk_common_full_dest_files: $(ndk_common_full_dest_files)"
diff --git a/pdk/ndk/README b/pdk/ndk/README
index a890ab2..ce3374b 100644
--- a/pdk/ndk/README
+++ b/pdk/ndk/README
@@ -1,10 +1,19 @@
Using the Native Development Kit (NDK)
version 1.2
+PRECONDITIONS
+
+The Native Development Kit may be installed on either Linux or OS X.
+
+The NDK must be installed on a case-sensitive file system. Linux
+file systems are always case-sensitive, but the default OS X file
+system is case-insenstive. A case-sensitive file sytem can be
+created either by partitioning your drive to include a case-sensitive
+partition or by creating a disk image that is case-sensitive.
STEP 1
Installing arm-eabi-gcc
---------
+-----------------------
1) Untar the android_ndk.tar.gz:
@@ -12,148 +21,10 @@
This will create a directory called ndk. It should include a README file (this
file) and the following directories: config, include, lib, sample and toolchain.
-
-2) Install gcc-4.2.1 and binutils:
-
- cd ndk/toolchain
- make unpack
- make patch
- make build
-{Note: you may have to add a parameter to the make build line like this:
-
- make build PREFIX:=<path_to_ndk_directory>/toolchain/arm-eabi
-
-which will put gcc in the correct directory instead of the default directory.
-You can also edit the toolchain/config.mk file to modify the PREFIX line to:
-
-PREFIX := $(CURDIR)/../../arm-eabi}
-
-At the end of this process arm-eabi-gcc should be installed in the directory
-ndk/toolchain/arm-eabi/bin.
-
STEP 2
-Building an application.
---------
-
-1) Test the ndk install by building the hello world sample application:
-
- cd ../sample
- make clean
- make
-
-The sample application uses hello.c to construct the hello binary, which you
-can load and run on the ARM device. To achieve proper runtime behavior, verify
-that:
- * crtbegin_dynamic.o is the first linked object file
- * crtend_android.o is last linked object.
-Both are set by the config.mk file in ndk/config.
-
-2) Test that this works correctly by attaching your ARM-based device to the USB
-port and installing the application (hello) you just made by (in the commands
-below # is the ARM device's shell prompt):
-
- adb push hello system/app
- adb shell
- # cd system/app
- # ./hello
- Hello from the NDK; no user libraries.
- # exit
-
-3) You may also build the c++ binary hello_cpp.cpp into an application:
-
- make -f Makefile.hello_cpp clean
- make -f Makefile.hello_cpp hello_cpp
-
-This uses the hello_cpp.cpp and hello_cpp.h files to construct the hello_cpp
-binary application, which you can load and run on the ARM device. Note that
-we do not provide for C++ exceptions thus you must use the -fno-exceptions flag
-when compiling.
-
- adb push hello_cpp system/app
- adb shell
- # cd system/app
- # ./hello_cpp
- C++ example printing message: Hello world!
- # exit
-
-
-STEP 3
-Building and using a library
+Samples
-------
-Makefile.lib in ndk/sample shows how to make either a shared library or a
-static library from the hellolibrary.c source. The example makes the libraries
-libhello-shared.so and libhello-static.a .
-
-Makefile.uselib then shows how to make an application that links against either
-a shared or a static library. They examples shows how to build the two
-applications use_hellolibrary-so and use-hellolibrary-a from the source
-use_hellolibrary.c.
-
-1) To make a shared library and an application that uses it:
-
- make -f Makefile.lib clean
- make -f Makefile.lib sharedlib
- make -f Makefile.uselib clean
- make -f Makefile.uselib use_hellolibrary-so
-
-2) Copy the shared library libhello-shared.so to /system/lib (or the location
-in which shared libraries are found by the kernel on your ARM-based device.)
-
- adb push libhello-shared.so system/lib
-
-You would not typically use the -shared or -static extensions in the filename,
-but the distinction is important in the case where a static and shared library
-are made in the same directory. Giving the files different names allows you to
-override the link defaults that default to a static library of the same name.
-
-3) The application, use_hellolibrary-so, can now be tested by loading and
-running on the ARM device.
-
- adb push use_hellolibrary-so /system/app
- adb shell
- # cd system/app
- # ./use_hellolibrary-so
- Library printing message: Hello from the NDK.
- # exit
-
-4) To make a static library:
-
- make -f Makefile.lib clean
- make -f Makefile.lib staticlib
- make -f Makefile.uselib clean
- make -f Makefile.uselib use_hellolibrary-a
-
-5) Test the application use_hellolibrary-a by loading and running it on the ARM
-device.
-
- adb push use_hellolibrary-a system/app
- adb shell
- # cd system/app
- # ./use_hellolibrary-a
- Library printing message: Hello from the NDK.
- # exit
-
-
-SUMMARY:
----------
-
-To make everything execute the following:
-
-make clean
-make
-make -f Makefile.lib clean
-make -f Makefile.lib
-make -f Makefile.uselib clean
-make -f Makefile.uselib
-make -f Makefile.hello_cpp clean
-make -f Makefile.hello_cpp hello_cpp
-
-
-You should have:
- * The libraries libhello-static.a and libhello-shared.so built, the latter
- ready for installation,
- * The applications hello, use_hellolibrary-a, and use_hellolibrary-so
- available for installation on the ARM device, and
+Look in the "samples" directory for samples of how to use the NDK.
diff --git a/pdk/ndk/config/config.mk b/pdk/ndk/config/config.mk
index 94507d6..a6972b1 100644
--- a/pdk/ndk/config/config.mk
+++ b/pdk/ndk/config/config.mk
@@ -1,13 +1,15 @@
+# Assumes PREBUILT is defined to point to the correct flavor of the prebuilt
+# directory in the Android source tree
-CC := $(NDK_BASE)/toolchain/arm-eabi/bin/arm-eabi-gcc
-AR := $(NDK_BASE)/toolchain/arm-eabi/bin/arm-eabi-ar
+CC := $(PREBUILT)/toolchain/arm-eabi-4.2.1/bin/arm-eabi-gcc
+AR := $(PREBUILT)/toolchain/arm-eabi-4.2.1/bin/arm-eabi-ar
-INC := -I$(NDK_BASE)/include/bionic/arch-arm/include \
- -I$(NDK_BASE)/include/bionic/include \
- -I$(NDK_BASE)/include/kernel/include \
- -I$(NDK_BASE)/include/libm/include \
- -I$(NDK_BASE)/include/libm/include/arm \
- -I$(NDK_BASE)/include/libstdc++/include
+INC := -I$(NDK_BASE)/include/bionic/libc/arch-arm/include \
+ -I$(NDK_BASE)/include/kernel/include \
+ -I$(NDK_BASE)/include/bionic/libm/include \
+ -I$(NDK_BASE)/include/bionic/libm/include/arm \
+ -I$(NDK_BASE)/include/bionic/libc/include \
+ -I$(NDK_BASE)/include/bionic/libstdc++/include
LINK := -nostdlib -Bdynamic \
-Wl,-T,$(NDK_BASE)/config/armelf.x \
diff --git a/pdk/ndk/sample/Makefile b/pdk/ndk/samples/sample/Makefile
similarity index 94%
rename from pdk/ndk/sample/Makefile
rename to pdk/ndk/samples/sample/Makefile
index e5b8151..a66ae86 100644
--- a/pdk/ndk/sample/Makefile
+++ b/pdk/ndk/samples/sample/Makefile
@@ -1,5 +1,5 @@
-NDK_BASE := ..
+NDK_BASE := ../..
include $(NDK_BASE)/config/config.mk
diff --git a/pdk/ndk/sample/Makefile.hello_cpp b/pdk/ndk/samples/sample/Makefile.hello_cpp
similarity index 94%
rename from pdk/ndk/sample/Makefile.hello_cpp
rename to pdk/ndk/samples/sample/Makefile.hello_cpp
index f461bdb..5d82b66 100644
--- a/pdk/ndk/sample/Makefile.hello_cpp
+++ b/pdk/ndk/samples/sample/Makefile.hello_cpp
@@ -1,5 +1,5 @@
-NDK_BASE := ..
+NDK_BASE := ../..
include $(NDK_BASE)/config/config.mk
diff --git a/pdk/ndk/sample/Makefile.lib b/pdk/ndk/samples/sample/Makefile.lib
similarity index 77%
rename from pdk/ndk/sample/Makefile.lib
rename to pdk/ndk/samples/sample/Makefile.lib
index 68b61ec..fbb5a14 100644
--- a/pdk/ndk/sample/Makefile.lib
+++ b/pdk/ndk/samples/sample/Makefile.lib
@@ -1,12 +1,15 @@
-NDK_BASE := ..
+NDK_BASE := ../..
include $(NDK_BASE)/config/config.mk
+# Assumes PREBUILT is defined to point to the correct flavor of the prebuilt
+# directory in the Android source tree
+
SOURCES := hellolibrary.c
OBJECTS := $(SOURCES:.c=.o)
LIBS := -lc -lm
-ALIB := $(NDK_BASE)/toolchain/arm-eabi/lib/gcc/arm-eabi/4.2.1/interwork/libgcc.a
+ALIB := $(PREBUILT)/toolchain/arm-eabi-4.2.1/lib/gcc/arm-eabi/4.2.1/interwork/libgcc.a
all: sharedlib staticlib
diff --git a/pdk/ndk/sample/Makefile.uselib b/pdk/ndk/samples/sample/Makefile.uselib
similarity index 95%
rename from pdk/ndk/sample/Makefile.uselib
rename to pdk/ndk/samples/sample/Makefile.uselib
index b677928..b44eae2 100644
--- a/pdk/ndk/sample/Makefile.uselib
+++ b/pdk/ndk/samples/sample/Makefile.uselib
@@ -1,4 +1,5 @@
-NDK_BASE := ..
+
+NDK_BASE := ../..
include $(NDK_BASE)/config/config.mk
diff --git a/pdk/ndk/samples/sample/README b/pdk/ndk/samples/sample/README
new file mode 100644
index 0000000..64e99de
--- /dev/null
+++ b/pdk/ndk/samples/sample/README
@@ -0,0 +1,135 @@
+Building native code applications and libraries
+
+STEP 1
+Building an application.
+--------
+
+0) set the environment variable PREBUILT to point to the Android prebuilt directory
+ export PREBUILT=<path_to_android_src>/prebuilt/<platform>
+
+where you type in the actual path to the android source in place of <path_to_android_src>
+and the platform you are using instead of <platform>: either linux-x86 or darwin-x86
+
+1) Test the ndk install by building the hello world sample application:
+
+ cd <your_ndk_base>/samples/sample
+ make clean
+ make
+
+The sample application uses hello.c to construct the hello binary, which you
+can load and run on the ARM device. To achieve proper runtime behavior, verify
+that:
+ * crtbegin_dynamic.o is the first linked object file
+ * crtend_android.o is last linked object.
+Both are set by the config.mk file in ndk/config.
+
+2) Test that this works correctly by attaching your ARM-based device to the USB
+port and installing the application (hello) you just made by (in the commands
+below # is the ARM device's shell prompt):
+
+NOTE: need a development build so remount opens system permissions
+
+ adb remount
+ adb push hello system/app
+ adb shell
+ # cd system/app
+ # ./hello
+ Hello from the NDK; no user libraries.
+ # exit
+
+3) You may also build the c++ binary hello_cpp.cpp into an application:
+
+ make -f Makefile.hello_cpp clean
+ make -f Makefile.hello_cpp hello_cpp
+
+This uses the hello_cpp.cpp and hello_cpp.h files to construct the hello_cpp
+binary application, which you can load and run on the ARM device. Note that
+we do not provide for C++ exceptions thus you must use the -fno-exceptions flag
+when compiling.
+
+ adb push hello_cpp system/app
+ adb shell
+ # cd system/app
+ # ./hello_cpp
+ C++ example printing message: Hello world!
+ # exit
+
+
+STEP 2
+Building and using a library
+-------
+
+Makefile.lib in ndk/sample shows how to make either a shared library or a
+static library from the hellolibrary.c source. The example makes the libraries
+libhello-shared.so and libhello-static.a .
+
+Makefile.uselib then shows how to make an application that links against either
+a shared or a static library. They examples shows how to build the two
+applications use_hellolibrary-so and use-hellolibrary-a from the source
+use_hellolibrary.c.
+
+1) To make a shared library and an application that uses it:
+
+ make -f Makefile.lib clean
+ make -f Makefile.lib sharedlib
+ make -f Makefile.uselib clean
+ make -f Makefile.uselib use_hellolibrary-so
+
+2) Copy the shared library libhello-shared.so to /system/lib (or the location
+in which shared libraries are found by the kernel on your ARM-based device.)
+
+ adb push libhello-shared.so system/lib
+
+You would not typically use the -shared or -static extensions in the filename,
+but the distinction is important in the case where a static and shared library
+are made in the same directory. Giving the files different names allows you to
+override the link defaults that default to a static library of the same name.
+
+3) The application, use_hellolibrary-so, can now be tested by loading and
+running on the ARM device.
+
+ adb push use_hellolibrary-so /system/app
+ adb shell
+ # cd system/app
+ # ./use_hellolibrary-so
+ Library printing message: Hello from the NDK.
+ # exit
+
+4) To make a static library:
+
+ make -f Makefile.lib clean
+ make -f Makefile.lib staticlib
+ make -f Makefile.uselib clean
+ make -f Makefile.uselib use_hellolibrary-a
+
+5) Test the application use_hellolibrary-a by loading and running it on the ARM
+device.
+
+ adb push use_hellolibrary-a system/app
+ adb shell
+ # cd system/app
+ # ./use_hellolibrary-a
+ Library printing message: Hello from the NDK.
+ # exit
+
+
+SUMMARY:
+---------
+
+To make everything execute the following:
+
+make clean
+make
+make -f Makefile.lib clean
+make -f Makefile.lib
+make -f Makefile.uselib clean
+make -f Makefile.uselib
+make -f Makefile.hello_cpp clean
+make -f Makefile.hello_cpp hello_cpp
+
+
+You should have:
+ * The libraries libhello-static.a and libhello-shared.so built, the latter
+ ready for installation,
+ * The applications hello, use_hellolibrary-a, and use_hellolibrary-so
+ available for installation on the ARM device.
diff --git a/pdk/ndk/sample/hello.c b/pdk/ndk/samples/sample/hello.c
similarity index 100%
rename from pdk/ndk/sample/hello.c
rename to pdk/ndk/samples/sample/hello.c
diff --git a/pdk/ndk/sample/hello_cpp.cpp b/pdk/ndk/samples/sample/hello_cpp.cpp
similarity index 100%
rename from pdk/ndk/sample/hello_cpp.cpp
rename to pdk/ndk/samples/sample/hello_cpp.cpp
diff --git a/pdk/ndk/sample/hello_cpp.h b/pdk/ndk/samples/sample/hello_cpp.h
similarity index 100%
rename from pdk/ndk/sample/hello_cpp.h
rename to pdk/ndk/samples/sample/hello_cpp.h
diff --git a/pdk/ndk/sample/hellolibrary.c b/pdk/ndk/samples/sample/hellolibrary.c
similarity index 100%
rename from pdk/ndk/sample/hellolibrary.c
rename to pdk/ndk/samples/sample/hellolibrary.c
diff --git a/pdk/ndk/sample/use_hellolibrary.c b/pdk/ndk/samples/sample/use_hellolibrary.c
similarity index 100%
rename from pdk/ndk/sample/use_hellolibrary.c
rename to pdk/ndk/samples/sample/use_hellolibrary.c
diff --git a/pdk/ndk/samples/samplejni/AndroidManifest.xml b/pdk/ndk/samples/samplejni/AndroidManifest.xml
new file mode 100644
index 0000000..450eb0b
--- /dev/null
+++ b/pdk/ndk/samples/samplejni/AndroidManifest.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.jniexample"
+ android:versionCode="1"
+ android:versionName="1.0.0">
+ <application android:icon="@drawable/icon" android:label="@string/app_name">
+ <activity android:name=".JNIExample"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
\ No newline at end of file
diff --git a/pdk/ndk/samples/samplejni/Makefile b/pdk/ndk/samples/samplejni/Makefile
new file mode 100644
index 0000000..18e97df
--- /dev/null
+++ b/pdk/ndk/samples/samplejni/Makefile
@@ -0,0 +1,45 @@
+# Package a shared library into an APK
+
+NDK_BASE := ../..
+
+# Assume ANDROID_SDK_BASE is defined to point to the base of the Android SDK
+# Assumes PREBUILT is defined to point to the prebuilt directory of the Android source
+
+include $(NDK_BASE)/config/config.mk
+
+SOURCES := native.cpp
+OBJECTS := $(SOURCES:.cpp=.o)
+LIBS := -lc -lm
+ALIB := $(PREBUILT)/toolchain/arm-eabi-4.2.1/lib/gcc/arm-eabi/4.2.1/interwork/libgcc.a
+
+APKBUILDER := $(ANDROID_SDK_BASE)/tools/apkbuilder
+
+APK_INPUT_DIR := bin
+APK_OUTPUT_DIR := bin/full
+
+APK_NAME := JNIExample.apk
+INPUT_APK := $(APK_INPUT_DIR)/$(APK_NAME)
+OUTPUT_APK := $(APK_OUTPUT_DIR)/$(APK_NAME)
+APK_STAGE := $(APK_OUTPUT_DIR)/temp
+
+JNI_LIBS := libnative.so
+
+all: $(OUTPUT_APK)
+
+$(OUTPUT_APK) : $(INPUT_APK) $(JNI_LIBS)
+ rm -rf $(APK_STAGE)
+ mkdir -p $(APK_STAGE)
+ unzip $(INPUT_APK) -d $(APK_STAGE)
+ mkdir -p $(APK_STAGE)/lib/armeabi
+ cp $(JNI_LIBS) $(APK_STAGE)/lib/armeabi
+ $(APKBUILDER) $(OUTPUT_APK) -v -rf $(APK_STAGE)
+ rm -rf $(APK_STAGE)
+
+libnative.so: native.o
+ $(CC) -nostdlib -Wl,-soname,libhello-shared.so -Wl,-shared,-Bsymbolic -L$(NDK_BASE)/lib $^ $(LIBS) -o $@ -Wl,--no-undefined $(ALIB)
+
+native.o: native.cpp
+ $(CC) -c -fpic $(INC) -I$(NDK_BASE)/include/nativehelper -o $@ $^
+
+clean:
+ rm -rf *.o libnative.so $(APK_OUTPUT_DIR)
diff --git a/pdk/ndk/samples/samplejni/README b/pdk/ndk/samples/samplejni/README
new file mode 100644
index 0000000..a821b7b
--- /dev/null
+++ b/pdk/ndk/samples/samplejni/README
@@ -0,0 +1,43 @@
+JNI Example
+
+This sample shows how to build a native code library, package it into an APK, and call it using JNI.
+
+Prerequesites
+
+You must install the Android SDK in order to build the Java APK. The Android SDK can be downloaded
+from
+
+http://code.google.com/android/download.html
+
+Build Steps:
+
+1) Create an Eclipse project to for the Java code.
+
+ Launch Eclipse
+ Choose File : New : Project...
+ Choose Android : Android Project
+ Choose Next
+ Enter "JNIExample" into the Project name: field.
+ Choose "Create project from existing source"
+ Click the Browse button and browse to the ndk/samplejni directory
+
+ Click Finish
+
+2) Build the Eclipse Project
+
+ Select the JNIExample project in the Package Explorer
+ Make sure that the menu item Project:Build Automatically is not checked.
+ Choose Project:Build
+
+ The resulting apk file ends up in bin/full/JNIExample.apk
+
+2) Build the shared library, insert the shared library into the APK file and resign the
+ shared library.
+
+ ANDROID_SDK_BASE=<directory where SDK is installed> make
+
+Install the APK on the device:
+
+ adb install -r bin/full/JNIExample.apk
+
+Once the application is installed, you can run it by tapping on the "JNI Example" icon.
diff --git a/pdk/ndk/samples/samplejni/native.cpp b/pdk/ndk/samples/samplejni/native.cpp
new file mode 100644
index 0000000..2e5fa4d
--- /dev/null
+++ b/pdk/ndk/samples/samplejni/native.cpp
@@ -0,0 +1,85 @@
+#include <jni.h>
+#include <stdio.h>
+
+static jint
+add(JNIEnv *env, jobject thiz, jint a, jint b) {
+int result = a + b;
+ printf("%d + %d = %d", a, b, result);
+ return result;
+}
+
+static const char *classPathName = "com/example/jniexample/Native";
+
+static JNINativeMethod methods[] = {
+ {"add", "(II)I", (void*)add },
+};
+
+/*
+ * Register several native methods for one class.
+ */
+static int registerNativeMethods(JNIEnv* env, const char* className,
+ JNINativeMethod* gMethods, int numMethods)
+{
+ jclass clazz;
+
+ clazz = env->FindClass(className);
+ if (clazz == NULL) {
+ fprintf(stderr, "Native registration unable to find class '%s'", className);
+ return JNI_FALSE;
+ }
+ if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
+ fprintf(stderr, "RegisterNatives failed for '%s'", className);
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+/*
+ * Register native methods for all classes we know about.
+ */
+static int registerNatives(JNIEnv* env)
+{
+ if (!registerNativeMethods(env, classPathName,
+ methods, sizeof(methods) / sizeof(methods[0]))) {
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+/*
+ * Set some test stuff up.
+ *
+ * Returns the JNI version on success, -1 on failure.
+ */
+
+typedef union {
+ JNIEnv* env;
+ void* venv;
+} UnionJNIEnvToVoid;
+
+jint JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+ UnionJNIEnvToVoid uenv;
+ uenv.venv = NULL;
+ jint result = -1;
+ JNIEnv* env = NULL;
+
+ printf("JNI_OnLoad");
+
+ if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
+ fprintf(stderr, "GetEnv failed");
+ goto bail;
+ }
+ env = uenv.env;
+
+ if (!registerNatives(env)) {
+ fprintf(stderr, "registerNatives failed");
+ }
+
+ result = JNI_VERSION_1_4;
+
+bail:
+ return result;
+}
diff --git a/pdk/ndk/samples/samplejni/res/drawable/icon.png b/pdk/ndk/samples/samplejni/res/drawable/icon.png
new file mode 100644
index 0000000..7502484
--- /dev/null
+++ b/pdk/ndk/samples/samplejni/res/drawable/icon.png
Binary files differ
diff --git a/pdk/ndk/samples/samplejni/res/values/strings.xml b/pdk/ndk/samples/samplejni/res/values/strings.xml
new file mode 100644
index 0000000..a647beb
--- /dev/null
+++ b/pdk/ndk/samples/samplejni/res/values/strings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">JNI Example</string>
+</resources>
diff --git a/pdk/ndk/samples/samplejni/src/com/example/jniexample/JNIExample.java b/pdk/ndk/samples/samplejni/src/com/example/jniexample/JNIExample.java
new file mode 100644
index 0000000..315ee21
--- /dev/null
+++ b/pdk/ndk/samples/samplejni/src/com/example/jniexample/JNIExample.java
@@ -0,0 +1,25 @@
+package com.example.jniexample;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class JNIExample extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ TextView tv = new TextView(this);
+ int sum = Native.add(2, 3);
+ tv.setText("Native Code test: 2 + 3 = " + Integer.toString(sum));
+ setContentView(tv);
+ }
+}
+
+class Native {
+ static {
+ System.loadLibrary("native");
+ }
+
+ static native int add(int a, int b);
+}
diff --git a/samples/ApiDemos/AndroidManifest.xml b/samples/ApiDemos/AndroidManifest.xml
index 8c682ac..bfefbf0 100644
--- a/samples/ApiDemos/AndroidManifest.xml
+++ b/samples/ApiDemos/AndroidManifest.xml
@@ -92,14 +92,18 @@
</intent-filter>
</activity>
- <activity android:name=".app.SaveRestoreState" android:label="@string/activity_save_restore">
+ <activity android:name=".app.SaveRestoreState"
+ android:label="@string/activity_save_restore"
+ android:windowSoftInputMode="stateVisible|adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
- <activity android:name=".app.PersistentState" android:label="@string/activity_persistent">
+ <activity android:name=".app.PersistentState"
+ android:label="@string/activity_persistent"
+ android:windowSoftInputMode="stateVisible|adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
@@ -139,7 +143,9 @@
<activity android:name=".app.RedirectGetter">
</activity>
- <activity android:name=".app.CustomTitle" android:label="@string/activity_custom_title">
+ <activity android:name=".app.CustomTitle"
+ android:label="@string/activity_custom_title"
+ android:windowSoftInputMode="stateVisible|adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
@@ -261,7 +267,20 @@
</intent-filter>
</activity>
- <activity android:name=".app.StatusBarNotifications" android:label="App/Notification/Status Bar">
+ <!-- This is used to display a notification selected by the user
+ from StatusBarNotifications. Note the configuration here so
+ that the activity layers on top of whatever the user is doing,
+ allowing them to press back to return. -->
+ <activity android:name=".app.NotificationDisplay"
+ android:theme="@style/Theme.Transparent"
+ android:taskAffinity=""
+ android:excludeFromRecents="true"
+ android:noHistory="true">
+ </activity>
+
+ <activity android:name=".app.StatusBarNotifications"
+ android:label="App/Notification/Status Bar"
+ android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
@@ -444,6 +463,16 @@
</intent-filter>
</activity>
+
+ <!-- Voice Recognition Samples -->
+
+ <activity android:name=".app.VoiceRecognition" android:label="@string/voice_recognition">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
<!-- ************************************* -->
<!-- CONTENT PACKAGE SAMPLES -->
<!-- ************************************* -->
@@ -1335,6 +1364,16 @@
</intent-filter>
</activity>
+ <activity android:name=".graphics.TouchRotateActivity"
+ android:label="Graphics/OpenGL ES/Touch Rotate"
+ android:theme="@android:style/Theme.NoTitleBar"
+ android:configChanges="orientation|keyboardHidden">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
<activity android:name=".graphics.PolyToPoly" android:label="Graphics/PolyToPoly">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -1596,6 +1635,13 @@
</intent-filter>
</activity>
+ <activity android:name=".text.Marquee" android:label="Text/Marquee">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
<activity android:name=".text.LogTextBox1" android:label="Text/LogTextBox">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
diff --git a/samples/ApiDemos/res/layout/link.xml b/samples/ApiDemos/res/layout/link.xml
index 07f8325..a65d000 100644
--- a/samples/ApiDemos/res/layout/link.xml
+++ b/samples/ApiDemos/res/layout/link.xml
@@ -4,9 +4,9 @@
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.
@@ -14,10 +14,43 @@
limitations under the License.
-->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/text"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:autoLink="all"
- android:text="@string/link_text"
- />
-
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <!-- Four TextView widgets, each one displaying text containing links. -->
+
+ <!-- text1 automatically linkifies things like URLs and phone numbers. -->
+ <TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/text1"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:autoLink="all"
+ android:text="@string/link_text_auto"
+ />
+
+ <!-- text2 uses a string resource containing explicit <a> tags to
+ specify links. -->
+ <TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/text2"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:text="@string/link_text_manual"
+ />
+
+ <!-- text3 builds the text in the Java code using HTML. -->
+ <TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/text3"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ />
+
+ <!-- text4 builds the text in the Java code without using HTML. -->
+ <TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/text4"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/marquee.xml b/samples/ApiDemos/res/layout/marquee.xml
new file mode 100644
index 0000000..6d40c84
--- /dev/null
+++ b/samples/ApiDemos/res/layout/marquee.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2008 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.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <Button
+ android:layout_width="150dip"
+ android:layout_height="wrap_content"
+ android:text="@string/marquee_default"
+ android:singleLine="true"
+ android:ellipsize="marquee"/>
+
+ <Button
+ android:layout_width="150dip"
+ android:layout_height="wrap_content"
+ android:text="@string/marquee_once"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:marqueeRepeatLimit="1"/>
+
+ <Button
+ android:layout_width="150dip"
+ android:layout_height="wrap_content"
+ android:text="@string/marquee_forever"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:marqueeRepeatLimit="marquee_forever"/>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/surface_view_overlay.xml b/samples/ApiDemos/res/layout/surface_view_overlay.xml
index c514206..a557e22 100644
--- a/samples/ApiDemos/res/layout/surface_view_overlay.xml
+++ b/samples/ApiDemos/res/layout/surface_view_overlay.xml
@@ -28,7 +28,7 @@
android:layout_height="0px"
android:layout_weight="1">
- <com.example.android.apis.graphics.GLSurfaceView android:id="@+id/glsurfaceview"
+ <android.opengl.GLSurfaceView android:id="@+id/glsurfaceview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
diff --git a/samples/ApiDemos/res/layout/voice_recognition.xml b/samples/ApiDemos/res/layout/voice_recognition.xml
new file mode 100644
index 0000000..2db4a72
--- /dev/null
+++ b/samples/ApiDemos/res/layout/voice_recognition.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2008 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.
+ -->
+
+<!-- This activity displays UI for launching voice recognition -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="4dip"
+ android:text="@string/voice_recognition_prompt" />
+
+ <Button android:id="@+id/btn_speak"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/speak_button" />
+
+ <ListView android:id="@+id/list"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1" />
+
+ </LinearLayout>
diff --git a/samples/ApiDemos/res/values/strings.xml b/samples/ApiDemos/res/values/strings.xml
index b1e12b8..2b2cc16 100644
--- a/samples/ApiDemos/res/values/strings.xml
+++ b/samples/ApiDemos/res/values/strings.xml
@@ -4,9 +4,9 @@
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.
@@ -44,7 +44,7 @@
whatever is behind it.</string>
<string name="activity_translucent_blur">App/Activity/Translucent Blur</string>
-
+
<string name="activity_save_restore">App/Activity/Save & Restore State</string>
<string name="save_restore_msg">Demonstration of saving and restoring activity state in onSaveInstanceState() and onCreate().</string>
<string name="saves_state">This text field saves its state:</string>
@@ -116,16 +116,16 @@
<string name="remote_call_failed">Failure calling remote service</string>
<string name="service_arguments_started">"Started with arguments: "</string>
- <string name="service_arguments_stopped">Finished arguments,
+ <string name="service_arguments_stopped">Finished arguments,
stopping.</string>
<string name="service_start_arguments_label">Sample Service Start Arguments
</string>
- <string name="activity_service_start_arguments_controller">App/Service/Service
+ <string name="activity_service_start_arguments_controller">App/Service/Service
Start Arguments Controller
</string>
- <string name="service_start_arguments_controller">This demonstrates how
- service can be started with arguments, and run until all arguments are
+ <string name="service_start_arguments_controller">This demonstrates how
+ service can be started with arguments, and run until all arguments are
processed.
</string>
<string name="start1_service">Start with \"One\"</string>
@@ -178,7 +178,7 @@
<string name="notifying_service_controller">This service will update a status bar notification
every 5 seconds for a minute</string>
-
+
<string name="activity_custom_title">App/Activity/Custom Title</string>
<string name="custom_title_left">Left is best</string>
<string name="custom_title_right">Right is always right</string>
@@ -189,6 +189,8 @@
<string name="menu_from_xml_instructions_press_menu">Select a menu resource and press the menu key.</string>
<string name="menu_from_xml_instructions_go_back">If you want to choose another menu resource, go back and re-run this activity.</string>
+ <string name="voice_recognition">App/Voice Recognition</string>
+
<!-- ============================== -->
<!-- app/content examples strings -->
<!-- ============================== -->
@@ -199,7 +201,7 @@
<string name="styled_text_prog">Assigned programmatically:</string>
<string name="activity_read_asset">Content/Assets/Read Asset</string>
-
+
<string name="activity_themes">Content/Resources/Themes</string>
<string name="activity_resources">Content/Resources/Resources</string>
@@ -216,23 +218,23 @@
<string name="short_right_notification">Short right.</string>
<string name="custom_notification">Custom Notification:</string>
<string name="custom_notification_button">With a Button</string>
-
+
<string name="status_bar_notifications_icons_only">Icons only</string>
<string name="status_bar_notifications_icons_and_marquee">Icons and marquee</string>
<string name="status_bar_notifications_remote_views">Use remote views in balloon</string>
<string name="status_bar_notifications_defaults">Use default values where applicable</string>
<string name="status_bar_notifications_happy">:-)</string>
- <string name="status_bar_notifications_ok">:-|</string>
- <string name="status_bar_notifications_sad">:-(</string>
+ <string name="status_bar_notifications_ok">:-|</string>
+ <string name="status_bar_notifications_sad">:-(</string>
<string name="status_bar_notifications_happy_message">I am happy</string>
<string name="status_bar_notifications_ok_message">I am ok</string>
- <string name="status_bar_notifications_sad_message">I am sad</string>
+ <string name="status_bar_notifications_sad_message">I am sad</string>
<string name="status_bar_notifications_clear">Clear notification</string>
<string name="status_bar_notifications_mood_title">Mood ring</string>
<string name="status_bar_notifications_default_sound">Sound</string>
<string name="status_bar_notifications_default_vibrate">Vibrate</string>
<string name="status_bar_notifications_default_all">All</string>
-
+
<!-- ============================== -->
<!-- app/dialog examples strings -->
<!-- ============================== -->
@@ -250,13 +252,13 @@
<string name="alert_dialog_two_buttons_title">
Lorem ipsum dolor sit aie consectetur adipiscing\nPlloaso mako nuto
siwuf cakso dodtos anr koop.
- </string>
+ </string>
<string name="alert_dialog_two_buttons_msg">Header title</string>
<string name="alert_dialog_two_buttons2_msg">
Plloaso mako nuto siwuf cakso dodtos anr koop a
cupy uf cak vux noaw yerw phuno. Whag schengos, uf efed, quiel
- ba mada su otrenzr.\n\nSwipontgwook proudgs hus yag su ba dagarmidad.
- Plasa maku noga wipont trenzsa schengos ent kaap zux comy.\n\nWipont trenz
+ ba mada su otrenzr.\n\nSwipontgwook proudgs hus yag su ba dagarmidad.
+ Plasa maku noga wipont trenzsa schengos ent kaap zux comy.\n\nWipont trenz
kipg naar mixent phona. Cak pwico siructiun
ruous nust apoply tyu cak Uhex sisulutiun munityuw uw dseg
</string>
@@ -266,10 +268,10 @@
<string name="alert_dialog_cancel">Cancel</string>
<string name="alert_dialog_progress_text1">34<xliff:g id="percent">%</xliff:g></string>
<string name="alert_dialog_progress_text2">145/305 KB</string>
-
+
<string name="select_dialog">Header title</string>
<string name="select_dialog_show">List dialog</string>
-
+
<!-- ============================== -->
<!-- app/menu examples strings -->
<!-- ============================== -->
@@ -295,7 +297,7 @@
<!-- ============================== -->
<!-- app/menu examples strings -->
<!-- ============================== -->
-
+
<string name="preferences_from_xml">App/Preferences/1. Preferences from XML</string>
<string name="launching_preferences">App/Preferences/2. Launching preferences</string>
<string name="preference_dependencies">App/Preferences/3. Preference dependencies</string>
@@ -305,7 +307,7 @@
<string name="launch_preference_activity">Launch PreferenceActivity</string>
<string name="counter_value_is">The counter value is</string>
-
+
<string name="inline_preferences">In-line preferences</string>
<string name="dialog_based_preferences">Dialog-based preferences</string>
<string name="launch_preferences">Launch preferences</string>
@@ -316,7 +318,7 @@
<string name="title_checkbox_preference">Checkbox preference</string>
<string name="summary_checkbox_preference">This is a checkbox</string>
-
+
<string name="title_yesno_preference">Yes or no preference</string>
<string name="summary_yesno_preference">An example that uses a yes/no dialog</string>
<string name="dialog_title_yesno_preference">Do you like bananas?</string>
@@ -349,7 +351,7 @@
<string name="summary_parent_preference">This is visually a parent</string>
<string name="title_child_preference">Child toggle</string>
<string name="summary_child_preference">This is visually a child</string>
-
+
<string name="example_preference_dependency">Example preference dependency</string>
<string name="title_wifi">WiFi</string>
<string name="title_wifi_settings">WiFi settings</string>
@@ -374,10 +376,10 @@
<string name="label_search_query">"Query String: "</string>
<string name="label_search_appdata">"Query App Data: "</string>
<string name="label_search_deliveredby">"Activity Method: "</string>
-
+
<string name="search_label">Search Demo</string>
<string name="search_hint">Search Demo Hint</string>
-
+
<!-- ================================ -->
<!-- app/shortcuts examples strings -->
<!-- ================================ -->
@@ -385,16 +387,24 @@
<string name="shortcuts">App/Launcher Shortcuts</string>
<string name="sample_shortcuts">ApiDemos</string>
<string name="shortcut_name">Sample</string>
-
+
<string name="msg_launcher_shortcuts">This activity creates shortcuts for the launcher (home screen), and receives intents from those shortcuts. To try it, return to the launcher and long-press to create a shortcut.</string>
<string name="label_intent">Intent:</string>
+ <!-- ============================== -->
+ <!-- app/voice recognition examples strings -->
+ <!-- ============================== -->
+
+ <string name="voice_recognition_prompt">This activity demonstrates the voice recognition APIs.</string>
+ <string name="speak_button">Speak!</string>
+ <string name="voice_recognition_results">Results:</string>
+
<!-- ============================ -->
<!-- graphics examples strings -->
<!-- ============================ -->
<string name="hide_me">Hide Me!</string>
-
+
<!-- ============================ -->
<!-- media examples strings -->
<!-- ============================ -->
@@ -426,13 +436,13 @@
<string name="table_layout_7_ctrlq">Ctrl-Q</string>
<string name="table_layout_8_quit">Quit</string>
<string name="table_layout_8_ctrlq">Ctrl-Q</string>
-
+
<string name="seekbar_tracking_on">Tracking on</string>
<string name="seekbar_tracking_off">Tracking off</string>
<string name="seekbar_from_touch">from touch</string>
-
+
<string name="ratingbar_rating">Rating:</string>
-
+
<!-- ============================== -->
<!-- GoogleLogin examples strings -->
<!-- ============================== -->
@@ -542,10 +552,20 @@
<string name="linear_layout_8_b">B</string>
<string name="linear_layout_8_c">C</string>
<string name="linear_layout_9_button">Button</string>
- <string name="link_text">This is some text. In this text are some things that are actionable. For instance, you can click on http://www.google.com and it will launch the web browser. You can click on google.com too. And, if you click on (415) 555-1212 it should dial the phone.</string>
+ <string name="link_text_auto"><b>text1:</b> This is some text. In
+ this text are some things that are actionable. For instance,
+ you can click on http://www.google.com and it will launch the
+ web browser. You can click on google.com too. And, if you
+ click on (415) 555-1212 it should dial the phone.
+ </string>
+ <string name="link_text_manual"><b>text2:</b> This is some other
+ text, with a <a href="http://www.google.com">link</a> specified
+ via an <a> tag. Use a \"tel:\" URL
+ to <a href="tel:4155551212">dial a phone number</a>.
+ </string>
<string name="list_8_new_photo">New photo</string>
<string name="list_8_clear_photos">Clear photos</string>
- <string name="list_8_no_photos">No photos</string>
+ <string name="list_8_no_photos">No photos</string>
<string name="progressbar_1_plus">+</string>
<string name="progressbar_1_minus">-</string>
<string name="progressbar_1_default_progress">Default progress:</string>
@@ -585,19 +605,19 @@
<string name="scrollbar_1_text">Lorem ipsum dolor sit amet.</string>
<string name="scrollbar_2_text">Lorem ipsum dolor sit amet.</string>
<string name="scrollbar_3_text">
- The Android platform is a software stack for mobile devices including an
- operating system, middleware and key applications. Developers can create
- applications for the platform using the Android SDK. Applications are written
- using the Java programming language and run on Dalvik, a custom virtual
+ The Android platform is a software stack for mobile devices including an
+ operating system, middleware and key applications. Developers can create
+ applications for the platform using the Android SDK. Applications are written
+ using the Java programming language and run on Dalvik, a custom virtual
machine designed for embedded use which runs on top of a Linux kernel.
- If you want to know how to develop applications for Android, you're in the
- right place. This site provides a variety of documentation that will help you
+ If you want to know how to develop applications for Android, you're in the
+ right place. This site provides a variety of documentation that will help you
learn about Android and develop mobile applications for the platform.
- An early look at the the Android SDK is also available. It includes sample
- projects with source code, development tools, an emulator, and of course all
- the libraries you'll need to build an Android application. What would it take
+ An early look at the the Android SDK is also available. It includes sample
+ projects with source code, development tools, an emulator, and of course all
+ the libraries you'll need to build an Android application. What would it take
to build a better mobile phone?
</string>
<string name="spinner_1_color">Color:</string>
@@ -722,6 +742,10 @@
<string name="notify_with_text_long_notify_text">Show Long Notification</string>
<string name="notify_with_text_short_notify_text">Show Short Notification</string>
+ <string name="marquee_default">This use the default marquee animation limit of 3</string>
+ <string name="marquee_once">This will run the marquee animation once</string>
+ <string name="marquee_forever">This will run the marquee animation forever</string>
+
<string name="table_layout_10_password_text"></string>
<string name="table_layout_10_username_text"></string>
@@ -730,7 +754,7 @@
<string name="date_widgets_example_dateDisplay_text"></string>
<string name="date_widgets_example_pickTime_text">change the time</string>
<string name="date_widgets_example_pickDate_text">change the date</string>
-
+
<string name="buttons_1_normal">Normal</string>
<string name="buttons_1_right">Right</string>
<string name="buttons_1_small">Small</string>
@@ -739,7 +763,7 @@
<string name="buttons_1_small_up">S U</string>
<string name="buttons_1_small_down">S D</string>
<string name="buttons_1_toggle">Toggle</string>
-
+
<string name="expandable_list_sample_action">Sample action</string>
<string name="chronometer_start">Start</string>
@@ -754,8 +778,8 @@
<!-- ============================ -->
<string name="vibrate">Vibrate</string>
-
-
+
+
<string name="image_view_large_normal">Large image at normal size</string>
<string name="image_view_large_at_most">Large image scaled to at most 50x50</string>
<string name="image_view_large_at_most_padded">Large image scaled to at most 70x70 with padding</string>
@@ -764,7 +788,7 @@
<string name="image_view_small_at_most">Small image scaled to at most 50x50</string>
<string name="image_view_small_at_most_padded">Small image scaled to at most 70x70 with padding</string>
<string name="image_view_small_exactly_padded">Small image scaled to exactly 70x70 with padding</string>
-
+
<!-- Shouldn't be localized -->
<string name="textColorPrimary">textColorPrimary</string>
<string name="textColorSecondary">textColorSecondary</string>
diff --git a/samples/ApiDemos/src/com/android/samples/app/VoiceRecognition.java b/samples/ApiDemos/src/com/android/samples/app/VoiceRecognition.java
new file mode 100644
index 0000000..aa45c8e
--- /dev/null
+++ b/samples/ApiDemos/src/com/android/samples/app/VoiceRecognition.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2008 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.samples.app;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.ListView;
+
+import com.example.android.apis.R;
+
+import java.util.ArrayList;
+
+public class VoiceRecognition extends Activity {
+
+ private static final int VOICE_RECOGNITION_REQUEST_CODE = 1234;
+
+ private ListView mList;
+
+ /**
+ * Called with the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Inflate our UI from its XML layout description.
+ setContentView(R.layout.voice_recognition);
+
+ // Get display items for later interaction
+ Button speakButton = (Button) findViewById(R.id.btn_speak);
+
+ mList = (ListView) findViewById(R.id.list);
+
+ // Attach actions to buttons
+ speakButton.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ startVoiceRecognitionActivity();
+ }
+ });
+ }
+
+ void startVoiceRecognitionActivity() {
+ Intent intent = new Intent("android.intent.action.VOICE_RECOGNITION");
+ this.startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+
+ android.util.Log.d("mike", "************** onActivityResult" + data );
+
+ if (requestCode == VOICE_RECOGNITION_REQUEST_CODE && resultCode == RESULT_OK) {
+ ArrayList<String>matches = data.getStringArrayListExtra("queries");
+
+
+ android.util.Log.d("mike", "************** onActivityResult" + matches);
+
+ mList.setAdapter(new ArrayAdapter<String>(this,
+ android.R.layout.simple_list_item_1, matches));
+ }
+
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/NotificationDisplay.java b/samples/ApiDemos/src/com/example/android/apis/app/NotificationDisplay.java
new file mode 100644
index 0000000..a6c20ea
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/NotificationDisplay.java
@@ -0,0 +1,85 @@
+/*
+ * 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.example.android.apis.app;
+
+// Need the following import to get access to the app resources, since this
+// class is in a sub-package.
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.app.NotificationManager;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+
+
+/**
+ * Activity used by StatusBarNotification to show the notification to the user.
+ */
+public class NotificationDisplay extends Activity implements View.OnClickListener {
+ /**
+ * Initialization of the Activity after it is first created. Must at least
+ * call {@link android.app.Activity#setContentView setContentView()} to
+ * describe what is to be displayed in the screen.
+ */
+ @Override
+ protected void onCreate(Bundle icicle) {
+ // Be sure to call the super class.
+ super.onCreate(icicle);
+
+ // Have the system blur any windows behind this one.
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
+ WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
+
+ RelativeLayout container = new RelativeLayout(this);
+
+ ImageButton button = new ImageButton(this);
+ button.setImageResource(getIntent().getIntExtra("moodimg", 0));
+ button.setOnClickListener(this);
+
+ RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
+ RelativeLayout.LayoutParams.WRAP_CONTENT,
+ RelativeLayout.LayoutParams.WRAP_CONTENT);
+ lp.addRule(RelativeLayout.CENTER_IN_PARENT);
+
+ container.addView(button, lp);
+
+ setContentView(container);
+ }
+
+ public void onClick(View v) {
+ // The user has confirmed this notification, so remove it.
+ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
+ .cancel(R.layout.status_bar_notifications);
+
+ // Pressing on the button brings the user back to our mood ring,
+ // as part of the api demos app. Note the use of NEW_TASK here,
+ // since the notification display activity is run as a separate task.
+ Intent intent = new Intent(this, StatusBarNotifications.class);
+ intent.setAction(Intent.ACTION_MAIN);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+
+ // We're done.
+ finish();
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/SearchInvoke.java b/samples/ApiDemos/src/com/example/android/apis/app/SearchInvoke.java
index a625434..a8d350c 100644
--- a/samples/ApiDemos/src/com/example/android/apis/app/SearchInvoke.java
+++ b/samples/ApiDemos/src/com/example/android/apis/app/SearchInvoke.java
@@ -22,6 +22,7 @@
import android.app.AlertDialog;
import android.app.SearchManager;
import android.os.Bundle;
+import android.provider.SearchRecentSuggestions;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -111,6 +112,8 @@
// first, get rid of our menus (if any)
menu.removeItem(0);
+ menu.removeItem(1);
+
// next, add back item(s) based on current menu mode
switch (mMenuMode.getSelectedItemPosition())
{
@@ -131,6 +134,8 @@
item = menu.add( 0, 0, 0, "(Disabled)");
break;
}
+
+ item = menu.add(0, 1, 0, "Clear History");
return true;
}
@@ -167,6 +172,9 @@
break;
}
break;
+ case 1:
+ clearSearchHistory();
+ break;
}
return super.onOptionsItemSelected(item);
@@ -211,4 +219,23 @@
return true;
}
+ /**
+ * Any application that implements search suggestions based on previous actions (such as
+ * recent queries, page/items viewed, etc.) should provide a way for the user to clear the
+ * history. This gives the user a measure of privacy, if they do not wish for their recent
+ * searches to be replayed by other users of the device (via suggestions).
+ *
+ * This example shows how to clear the search history for apps that use
+ * android.provider.SearchRecentSuggestions. If you have developed a custom suggestions
+ * provider, you'll need to provide a similar API for clearing history.
+ *
+ * In this sample app we call this method from a "Clear History" menu item. You could also
+ * implement the UI in your preferences, or any other logical place in your UI.
+ */
+ private void clearSearchHistory() {
+ SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
+ SearchSuggestionSampleProvider.AUTHORITY, SearchSuggestionSampleProvider.MODE);
+ suggestions.clearHistory();
+ }
+
}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/StatusBarNotifications.java b/samples/ApiDemos/src/com/example/android/apis/app/StatusBarNotifications.java
index bc69e7b..97f6199 100644
--- a/samples/ApiDemos/src/com/example/android/apis/app/StatusBarNotifications.java
+++ b/samples/ApiDemos/src/com/example/android/apis/app/StatusBarNotifications.java
@@ -144,6 +144,19 @@
});
}
+ private PendingIntent makeMoodIntent(int moodId) {
+ // The PendingIntent to launch our activity if the user selects this
+ // notification. Note the use of FLAG_UPDATE_CURRENT so that if there
+ // is already an active matching pending intent, we will update its
+ // extras to be the ones passed in here.
+ PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
+ new Intent(this, NotificationDisplay.class)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ .putExtra("moodimg", moodId),
+ PendingIntent.FLAG_UPDATE_CURRENT);
+ return contentIntent;
+ }
+
private void setMood(int moodId, int textId, boolean showTicker) {
// In this sample, we'll use the same text for the ticker and the expanded notification
CharSequence text = getText(textId);
@@ -155,13 +168,9 @@
Notification notification = new Notification(moodId, tickerText,
System.currentTimeMillis());
- // The PendingIntent to launch our activity if the user selects this notification
- PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
- new Intent(this, StatusBarNotifications.class), 0);
-
// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this, getText(R.string.status_bar_notifications_mood_title),
- text, contentIntent);
+ text, makeMoodIntent(moodId));
// Send the notification.
// We use a layout id because it is a unique number. We use it later to cancel.
@@ -176,8 +185,7 @@
Notification notif = new Notification();
// This is who should be launched if the user selects our notification.
- notif.contentIntent = PendingIntent.getActivity(this, 0,
- new Intent(this, StatusBarNotifications.class), 0);
+ notif.contentIntent = makeMoodIntent(moodId);
// In this sample, we'll use the same text for the ticker and the expanded notification
CharSequence text = getText(textId);
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/BitmapDecode.java b/samples/ApiDemos/src/com/example/android/apis/graphics/BitmapDecode.java
index eb5712f..88f0c1d 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/BitmapDecode.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/BitmapDecode.java
@@ -28,6 +28,7 @@
import java.io.IOException;
import java.io.InputStream;
+import java.io.ByteArrayOutputStream;
public class BitmapDecode extends GraphicsActivity {
@@ -47,6 +48,19 @@
private Movie mMovie;
private long mMovieStart;
+ private static byte[] streamToBytes(InputStream is) {
+ ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
+ byte[] buffer = new byte[1024];
+ int len;
+ try {
+ while ((len = is.read(buffer)) >= 0) {
+ os.write(buffer, 0, len);
+ }
+ } catch (java.io.IOException e) {
+ }
+ return os.toByteArray();
+ }
+
public SampleView(Context context) {
super(context);
setFocusable(true);
@@ -87,7 +101,12 @@
mDrawable.setBounds(150, 20, 300, 100);
is = context.getResources().openRawResource(R.drawable.animated_gif);
- mMovie = Movie.decodeStream(is);
+ if (true) {
+ mMovie = Movie.decodeStream(is);
+ } else {
+ byte[] array = streamToBytes(is);
+ mMovie = Movie.decodeByteArray(array, 0, array.length);
+ }
}
@Override protected void onDraw(Canvas canvas) {
@@ -107,11 +126,17 @@
if (mMovieStart == 0) { // first time
mMovieStart = now;
}
- int relTime = (int)((now - mMovieStart) % mMovie.duration());
- mMovie.setTime(relTime);
- mMovie.draw(canvas, getWidth() - mMovie.width(),
- getHeight() - mMovie.height());
- invalidate();
+ if (mMovie != null) {
+ int dur = mMovie.duration();
+ if (dur == 0) {
+ dur = 1000;
+ }
+ int relTime = (int)((now - mMovieStart) % dur);
+ mMovie.setTime(relTime);
+ mMovie.draw(canvas, getWidth() - mMovie.width(),
+ getHeight() - mMovie.height());
+ invalidate();
+ }
}
}
}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java b/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java
index 8e6e158..ceff150 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java
@@ -23,7 +23,7 @@
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
-
+import java.io.IOException;
// ----------------------------------------------------------------------
@@ -64,7 +64,13 @@
// The Surface has been created, acquire the camera and tell it where
// to draw.
mCamera = Camera.open();
- mCamera.setPreviewDisplay(holder);
+ try {
+ mCamera.setPreviewDisplay(holder);
+ } catch (IOException exception) {
+ mCamera.release();
+ mCamera = null;
+ // TODO: add more exception handling logic here
+ }
}
public void surfaceDestroyed(SurfaceHolder holder) {
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/CubeRenderer.java b/samples/ApiDemos/src/com/example/android/apis/graphics/CubeRenderer.java
index 6117a60..527e2bc 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/CubeRenderer.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/CubeRenderer.java
@@ -17,8 +17,11 @@
package com.example.android.apis.graphics;
import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
+import android.opengl.GLSurfaceView;
+
/**
* Render a pair of tumbling cubes.
*/
@@ -29,7 +32,7 @@
mCube = new Cube();
}
- public void drawFrame(GL10 gl) {
+ public void onDrawFrame(GL10 gl) {
/*
* Usually, the first thing one might want to do is to clear
* the screen. The most efficient way of doing this is to use
@@ -84,7 +87,7 @@
}
}
- public void sizeChanged(GL10 gl, int width, int height) {
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
/*
@@ -99,7 +102,7 @@
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
}
- public void surfaceCreated(GL10 gl) {
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
/*
* By default, OpenGL enables features that improve quality
* but reduce performance. One might want to tweak that
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceView.java b/samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceView.java
deleted file mode 100644
index 16a17dd..0000000
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceView.java
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- * 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.example.android.apis.graphics;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-
-import java.util.ArrayList;
-import java.util.concurrent.Semaphore;
-
-import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.egl.EGL11;
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.egl.EGLContext;
-import javax.microedition.khronos.egl.EGLDisplay;
-import javax.microedition.khronos.egl.EGLSurface;
-import javax.microedition.khronos.opengles.GL;
-import javax.microedition.khronos.opengles.GL10;
-
-/**
- * An implementation of SurfaceView that uses the dedicated surface for
- * displaying an OpenGL animation. This allows the animation to run in a
- * separate thread, without requiring that it be driven by the update mechanism
- * of the view hierarchy.
- *
- * The application-specific rendering code is delegated to a GLView.Renderer
- * instance.
- */
-public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
- public GLSurfaceView(Context context) {
- super(context);
- init();
- }
-
- public GLSurfaceView(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
-
- private void init() {
- // Install a SurfaceHolder.Callback so we get notified when the
- // underlying surface is created and destroyed
- mHolder = getHolder();
- mHolder.addCallback(this);
- mHolder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
- }
-
- public SurfaceHolder getSurfaceHolder() {
- return mHolder;
- }
-
- public void setGLWrapper(GLWrapper glWrapper) {
- mGLWrapper = glWrapper;
- }
-
- public void setRenderer(Renderer renderer) {
- mGLThread = new GLThread(renderer);
- mGLThread.start();
- }
-
- public void surfaceCreated(SurfaceHolder holder) {
- mGLThread.surfaceCreated();
- }
-
- public void surfaceDestroyed(SurfaceHolder holder) {
- // Surface will be destroyed when we return
- mGLThread.surfaceDestroyed();
- }
-
- public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
- // Surface size or format has changed. This should not happen in this
- // example.
- mGLThread.onWindowResize(w, h);
- }
-
- /**
- * Inform the view that the activity is paused.
- */
- public void onPause() {
- mGLThread.onPause();
- }
-
- /**
- * Inform the view that the activity is resumed.
- */
- public void onResume() {
- mGLThread.onResume();
- }
-
- /**
- * Inform the view that the window focus has changed.
- */
- @Override public void onWindowFocusChanged(boolean hasFocus) {
- super.onWindowFocusChanged(hasFocus);
- mGLThread.onWindowFocusChanged(hasFocus);
- }
-
- /**
- * Queue an "event" to be run on the GL rendering thread.
- * @param r the runnable to be run on the GL rendering thread.
- */
- public void queueEvent(Runnable r) {
- mGLThread.queueEvent(r);
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- mGLThread.requestExitAndWait();
- }
-
- // ----------------------------------------------------------------------
-
- public interface GLWrapper {
- GL wrap(GL gl);
- }
-
- // ----------------------------------------------------------------------
-
- /**
- * A generic renderer interface.
- */
- public interface Renderer {
- /**
- * @return the EGL configuration specification desired by the renderer.
- */
- int[] getConfigSpec();
-
- /**
- * Surface created.
- * Called when the surface is created. Called when the application
- * starts, and whenever the GPU is reinitialized. This will
- * typically happen when the device awakes after going to sleep.
- * Set your textures here.
- */
- void surfaceCreated(GL10 gl);
- /**
- * Surface changed size.
- * Called after the surface is created and whenever
- * the OpenGL ES surface size changes. Set your viewport here.
- * @param gl
- * @param width
- * @param height
- */
- void sizeChanged(GL10 gl, int width, int height);
- /**
- * Draw the current frame.
- * @param gl
- */
- void drawFrame(GL10 gl);
- }
-
- /**
- * An EGL helper class.
- */
-
- private class EglHelper {
- public EglHelper() {
-
- }
-
- /**
- * Initialize EGL for a given configuration spec.
- * @param configSpec
- */
- public void start(int[] configSpec){
- /*
- * Get an EGL instance
- */
- mEgl = (EGL10) EGLContext.getEGL();
-
- /*
- * Get to the default display.
- */
- mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
-
- /*
- * We can now initialize EGL for that display
- */
- int[] version = new int[2];
- mEgl.eglInitialize(mEglDisplay, version);
-
- EGLConfig[] configs = new EGLConfig[1];
- int[] num_config = new int[1];
- mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1,
- num_config);
- mEglConfig = configs[0];
-
- /*
- * Create an OpenGL ES context. This must be done only once, an
- * OpenGL context is a somewhat heavy object.
- */
- mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig,
- EGL10.EGL_NO_CONTEXT, null);
-
- mEglSurface = null;
- }
-
- /*
- * Create and return an OpenGL surface
- */
- public GL createSurface(SurfaceHolder holder) {
- /*
- * The window size has changed, so we need to create a new
- * surface.
- */
- if (mEglSurface != null) {
-
- /*
- * Unbind and destroy the old EGL surface, if
- * there is one.
- */
- mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
- EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
- mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
- }
-
- /*
- * Create an EGL surface we can render into.
- */
- mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay,
- mEglConfig, holder, null);
-
- /*
- * Before we can issue GL commands, we need to make sure
- * the context is current and bound to a surface.
- */
- mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
- mEglContext);
-
-
- GL gl = mEglContext.getGL();
- if (mGLWrapper != null) {
- gl = mGLWrapper.wrap(gl);
- }
- return gl;
- }
-
- /**
- * Display the current render surface.
- * @return false if the context has been lost.
- */
- public boolean swap() {
- mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
-
- /*
- * Always check for EGL_CONTEXT_LOST, which means the context
- * and all associated data were lost (For instance because
- * the device went to sleep). We need to sleep until we
- * get a new surface.
- */
- return mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST;
- }
-
- public void finish() {
- if (mEglSurface != null) {
- mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
- EGL10.EGL_NO_SURFACE,
- EGL10.EGL_NO_CONTEXT);
- mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
- mEglSurface = null;
- }
- if (mEglContext != null) {
- mEgl.eglDestroyContext(mEglDisplay, mEglContext);
- mEglContext = null;
- }
- if (mEglDisplay != null) {
- mEgl.eglTerminate(mEglDisplay);
- mEglDisplay = null;
- }
- }
-
- EGL10 mEgl;
- EGLDisplay mEglDisplay;
- EGLSurface mEglSurface;
- EGLConfig mEglConfig;
- EGLContext mEglContext;
- }
-
- /**
- * A generic GL Thread. Takes care of initializing EGL and GL. Delegates
- * to a Renderer instance to do the actual drawing.
- *
- */
-
- class GLThread extends Thread {
- GLThread(Renderer renderer) {
- super();
- mDone = false;
- mWidth = 0;
- mHeight = 0;
- mRenderer = renderer;
- setName("GLThread");
- }
-
- @Override
- public void run() {
- /*
- * When the android framework launches a second instance of
- * an activity, the new instance's onCreate() method may be
- * called before the first instance returns from onDestroy().
- *
- * This semaphore ensures that only one instance at a time
- * accesses EGL.
- */
- try {
- try {
- sEglSemaphore.acquire();
- } catch (InterruptedException e) {
- return;
- }
- guardedRun();
- } catch (InterruptedException e) {
- // fall thru and exit normally
- } finally {
- sEglSemaphore.release();
- }
- }
-
- private void guardedRun() throws InterruptedException {
- mEglHelper = new EglHelper();
- /*
- * Specify a configuration for our opengl session
- * and grab the first configuration that matches is
- */
- int[] configSpec = mRenderer.getConfigSpec();
- mEglHelper.start(configSpec);
-
- GL10 gl = null;
- boolean tellRendererSurfaceCreated = true;
- boolean tellRendererSurfaceChanged = true;
-
- /*
- * This is our main activity thread's loop, we go until
- * asked to quit.
- */
- while (!mDone) {
-
- /*
- * Update the asynchronous state (window size)
- */
- int w, h;
- boolean changed;
- boolean needStart = false;
- synchronized (this) {
- Runnable r;
- while ((r = getEvent()) != null) {
- r.run();
- }
- if (mPaused) {
- mEglHelper.finish();
- needStart = true;
- }
- if(needToWait()) {
- while (needToWait()) {
- wait();
- }
- }
- if (mDone) {
- break;
- }
- changed = mSizeChanged;
- w = mWidth;
- h = mHeight;
- mSizeChanged = false;
- }
- if (needStart) {
- mEglHelper.start(configSpec);
- tellRendererSurfaceCreated = true;
- changed = true;
- }
- if (changed) {
- gl = (GL10) mEglHelper.createSurface(mHolder);
- tellRendererSurfaceChanged = true;
- }
- if (tellRendererSurfaceCreated) {
- mRenderer.surfaceCreated(gl);
- tellRendererSurfaceCreated = false;
- }
- if (tellRendererSurfaceChanged) {
- mRenderer.sizeChanged(gl, w, h);
- tellRendererSurfaceChanged = false;
- }
- if ((w > 0) && (h > 0)) {
- /* draw a frame here */
- mRenderer.drawFrame(gl);
-
- /*
- * Once we're done with GL, we need to call swapBuffers()
- * to instruct the system to display the rendered frame
- */
- mEglHelper.swap();
- }
- }
-
- /*
- * clean-up everything...
- */
- mEglHelper.finish();
- }
-
- private boolean needToWait() {
- return (mPaused || (! mHasFocus) || (! mHasSurface) || mContextLost)
- && (! mDone);
- }
-
- public void surfaceCreated() {
- synchronized(this) {
- mHasSurface = true;
- mContextLost = false;
- notify();
- }
- }
-
- public void surfaceDestroyed() {
- synchronized(this) {
- mHasSurface = false;
- notify();
- }
- }
-
- public void onPause() {
- synchronized (this) {
- mPaused = true;
- }
- }
-
- public void onResume() {
- synchronized (this) {
- mPaused = false;
- notify();
- }
- }
-
- public void onWindowFocusChanged(boolean hasFocus) {
- synchronized (this) {
- mHasFocus = hasFocus;
- if (mHasFocus == true) {
- notify();
- }
- }
- }
- public void onWindowResize(int w, int h) {
- synchronized (this) {
- mWidth = w;
- mHeight = h;
- mSizeChanged = true;
- }
- }
-
- public void requestExitAndWait() {
- // don't call this from GLThread thread or it is a guaranteed
- // deadlock!
- synchronized(this) {
- mDone = true;
- notify();
- }
- try {
- join();
- } catch (InterruptedException ex) {
- Thread.currentThread().interrupt();
- }
- }
-
- /**
- * Queue an "event" to be run on the GL rendering thread.
- * @param r the runnable to be run on the GL rendering thread.
- */
- public void queueEvent(Runnable r) {
- synchronized(this) {
- mEventQueue.add(r);
- }
- }
-
- private Runnable getEvent() {
- synchronized(this) {
- if (mEventQueue.size() > 0) {
- return mEventQueue.remove(0);
- }
-
- }
- return null;
- }
-
- private boolean mDone;
- private boolean mPaused;
- private boolean mHasFocus;
- private boolean mHasSurface;
- private boolean mContextLost;
- private int mWidth;
- private int mHeight;
- private Renderer mRenderer;
- private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>();
- private EglHelper mEglHelper;
- }
-
- private static final Semaphore sEglSemaphore = new Semaphore(1);
- private boolean mSizeChanged = true;
-
- private SurfaceHolder mHolder;
- private GLThread mGLThread;
- private GLWrapper mGLWrapper;
-}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceViewActivity.java b/samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceViewActivity.java
index aa46036..f852186 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceViewActivity.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceViewActivity.java
@@ -17,6 +17,7 @@
package com.example.android.apis.graphics;
import android.app.Activity;
+import android.opengl.GLSurfaceView;
import android.os.Bundle;
/**
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/SurfaceViewOverlay.java b/samples/ApiDemos/src/com/example/android/apis/graphics/SurfaceViewOverlay.java
index da2a1e5..45e5d60 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/SurfaceViewOverlay.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/SurfaceViewOverlay.java
@@ -17,6 +17,7 @@
package com.example.android.apis.graphics;
import android.app.Activity;
+import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/TouchRotateActivity.java b/samples/ApiDemos/src/com/example/android/apis/graphics/TouchRotateActivity.java
new file mode 100644
index 0000000..09d3694
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/TouchRotateActivity.java
@@ -0,0 +1,195 @@
+/*
+ * 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.example.android.apis.graphics;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.app.Activity;
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.view.MotionEvent;
+
+/**
+ * Wrapper activity demonstrating the use of {@link GLSurfaceView}, a view
+ * that uses OpenGL drawing into a dedicated surface.
+ *
+ * Shows:
+ * + How to redraw in response to user input.
+ */
+public class TouchRotateActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Create our Preview view and set it as the content of our
+ // Activity
+ mGLSurfaceView = new TouchSurfaceView(this);
+ setContentView(mGLSurfaceView);
+ mGLSurfaceView.requestFocus();
+ mGLSurfaceView.setFocusableInTouchMode(true);
+ }
+
+ @Override
+ protected void onResume() {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mGLSurfaceView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ mGLSurfaceView.onPause();
+ }
+
+ private GLSurfaceView mGLSurfaceView;
+}
+
+/**
+ * Implement a simple rotation control.
+ *
+ */
+class TouchSurfaceView extends GLSurfaceView {
+
+ public TouchSurfaceView(Context context) {
+ super(context);
+ mRenderer = new CubeRenderer();
+ setRenderer(mRenderer);
+ setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
+ }
+
+ @Override public boolean onTrackballEvent(MotionEvent e) {
+ mRenderer.mAngleX += e.getX() * TRACKBALL_SCALE_FACTOR;
+ mRenderer.mAngleY += e.getY() * TRACKBALL_SCALE_FACTOR;
+ requestRender();
+ return true;
+ }
+
+ @Override public boolean onTouchEvent(MotionEvent e) {
+ float x = e.getX();
+ float y = e.getY();
+ switch (e.getAction()) {
+ case MotionEvent.ACTION_MOVE:
+ float dx = x - mPreviousX;
+ float dy = y - mPreviousY;
+ mRenderer.mAngleX += dx * TOUCH_SCALE_FACTOR;
+ mRenderer.mAngleY += dy * TOUCH_SCALE_FACTOR;
+ requestRender();
+ }
+ mPreviousX = x;
+ mPreviousY = y;
+ return true;
+ }
+
+ /**
+ * Render a cube.
+ */
+ private class CubeRenderer implements GLSurfaceView.Renderer {
+ public CubeRenderer() {
+ mCube = new Cube();
+ }
+
+ public void onDrawFrame(GL10 gl) {
+ /*
+ * Usually, the first thing one might want to do is to clear
+ * the screen. The most efficient way of doing this is to use
+ * glClear().
+ */
+
+ gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+
+ /*
+ * Now we're ready to draw some 3D objects
+ */
+
+ gl.glMatrixMode(GL10.GL_MODELVIEW);
+ gl.glLoadIdentity();
+ gl.glTranslatef(0, 0, -3.0f);
+ gl.glRotatef(mAngleX, 0, 1, 0);
+ gl.glRotatef(mAngleY, 1, 0, 0);
+
+ gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+ gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
+
+ mCube.draw(gl);
+ }
+
+ public int[] getConfigSpec() {
+ // We want a depth buffer, don't care about the
+ // details of the color buffer.
+ int[] configSpec = {
+ EGL10.EGL_DEPTH_SIZE, 16,
+ EGL10.EGL_NONE
+ };
+ return configSpec;
+ }
+
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
+ gl.glViewport(0, 0, width, height);
+
+ /*
+ * Set our projection matrix. This doesn't have to be done
+ * each time we draw, but usually a new projection needs to
+ * be set when the viewport is resized.
+ */
+
+ float ratio = (float) width / height;
+ gl.glMatrixMode(GL10.GL_PROJECTION);
+ gl.glLoadIdentity();
+ gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
+ }
+
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ /*
+ * By default, OpenGL enables features that improve quality
+ * but reduce performance. One might want to tweak that
+ * especially on software renderer.
+ */
+ gl.glDisable(GL10.GL_DITHER);
+
+ /*
+ * Some one-time OpenGL initialization can be made here
+ * probably based on features of this particular context
+ */
+ gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,
+ GL10.GL_FASTEST);
+
+
+ gl.glClearColor(1,1,1,1);
+ gl.glEnable(GL10.GL_CULL_FACE);
+ gl.glShadeModel(GL10.GL_SMOOTH);
+ gl.glEnable(GL10.GL_DEPTH_TEST);
+ }
+ private Cube mCube;
+ public float mAngleX;
+ public float mAngleY;
+ }
+
+ private final float TOUCH_SCALE_FACTOR = 180.0f / 320;
+ private final float TRACKBALL_SCALE_FACTOR = 36.0f;
+ private CubeRenderer mRenderer;
+ private float mPreviousX;
+ private float mPreviousY;
+}
+
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/TranslucentGLSurfaceViewActivity.java b/samples/ApiDemos/src/com/example/android/apis/graphics/TranslucentGLSurfaceViewActivity.java
index 23558e4..750a47b 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/TranslucentGLSurfaceViewActivity.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/TranslucentGLSurfaceViewActivity.java
@@ -18,6 +18,7 @@
import android.app.Activity;
import android.graphics.PixelFormat;
+import android.opengl.GLSurfaceView;
import android.os.Bundle;
@@ -37,7 +38,7 @@
// of the cube:
mGLSurfaceView.setRenderer(new CubeRenderer(true));
// Use a surface format with an Alpha channel:
- mGLSurfaceView.getHolder().setFormat(PixelFormat.RGBA_8888);
+ mGLSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
setContentView(mGLSurfaceView);
}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleActivity.java b/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleActivity.java
index a09d0ca..59f3c6c 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleActivity.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleActivity.java
@@ -17,6 +17,7 @@
package com.example.android.apis.graphics;
import android.app.Activity;
+import android.opengl.GLSurfaceView;
import android.os.Bundle;
public class TriangleActivity extends Activity {
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleRenderer.java b/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleRenderer.java
index 5871857..451b927 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleRenderer.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleRenderer.java
@@ -16,7 +16,6 @@
package com.example.android.apis.graphics;
-import com.example.android.apis.R;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
@@ -24,15 +23,19 @@
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.opengl.GLUtils;
import android.os.SystemClock;
-import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.opengles.GL10;
+import com.example.android.apis.R;
public class TriangleRenderer implements GLSurfaceView.Renderer{
@@ -51,7 +54,7 @@
return configSpec;
}
- public void surfaceCreated(GL10 gl) {
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
/*
* By default, OpenGL enables features that improve quality
* but reduce performance. One might want to tweak that
@@ -113,7 +116,7 @@
bitmap.recycle();
}
- public void drawFrame(GL10 gl) {
+ public void onDrawFrame(GL10 gl) {
/*
* By default, OpenGL enables features that improve quality
* but reduce performance. One might want to tweak that
@@ -159,7 +162,7 @@
mTriangle.draw(gl);
}
- public void sizeChanged(GL10 gl, int w, int h) {
+ public void onSurfaceChanged(GL10 gl, int w, int h) {
gl.glViewport(0, 0, w, h);
/*
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/kube/Kube.java b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/Kube.java
index 4f9a488..9332941 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/kube/Kube.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/Kube.java
@@ -20,7 +20,7 @@
import android.os.Bundle;
import android.view.Window;
-import com.example.android.apis.graphics.GLSurfaceView;
+import android.opengl.GLSurfaceView;
import java.util.Random;
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/kube/KubeRenderer.java b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/KubeRenderer.java
index e1e7635..252f566 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/kube/KubeRenderer.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/KubeRenderer.java
@@ -16,9 +16,10 @@
package com.example.android.apis.graphics.kube;
-import com.example.android.apis.graphics.GLSurfaceView;
+import android.opengl.GLSurfaceView;
import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
@@ -36,7 +37,7 @@
mCallback = callback;
}
- public void drawFrame(GL10 gl) {
+ public void onDrawFrame(GL10 gl) {
if (mCallback != null) {
mCallback.animate();
}
@@ -82,7 +83,7 @@
return configSpec;
}
- public void sizeChanged(GL10 gl, int width, int height) {
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
/*
@@ -105,7 +106,7 @@
gl.glActiveTexture(GL10.GL_TEXTURE0);
}
- public void surfaceCreated(GL10 gl) {
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// Nothing special, don't have any textures we need to recreate.
}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextActivity.java b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextActivity.java
index c41b684..1e58dae 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextActivity.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextActivity.java
@@ -16,11 +16,10 @@
package com.example.android.apis.graphics.spritetext;
-import com.example.android.apis.graphics.GLSurfaceView;
-
import javax.microedition.khronos.opengles.GL;
import android.app.Activity;
+import android.opengl.GLSurfaceView;
import android.os.Bundle;
public class SpriteTextActivity extends Activity {
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextRenderer.java b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextRenderer.java
index 835e832..b9369cd 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextRenderer.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextRenderer.java
@@ -16,17 +16,6 @@
package com.example.android.apis.graphics.spritetext;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Paint;
-import android.opengl.GLU;
-import android.opengl.GLUtils;
-import android.os.SystemClock;
-
-import com.example.android.apis.R;
-import com.example.android.apis.graphics.GLSurfaceView;
-
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
@@ -35,8 +24,20 @@
import java.nio.ShortBuffer;
import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Paint;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLU;
+import android.opengl.GLUtils;
+import android.os.SystemClock;
+
+import com.example.android.apis.R;
+
public class SpriteTextRenderer implements GLSurfaceView.Renderer{
public SpriteTextRenderer(Context context) {
@@ -59,7 +60,7 @@
return configSpec;
}
- public void surfaceCreated(GL10 gl) {
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
/*
* By default, OpenGL enables features that improve quality
* but reduce performance. One might want to tweak that
@@ -141,7 +142,7 @@
mNumericSprite.initialize(gl, mLabelPaint);
}
- public void drawFrame(GL10 gl) {
+ public void onDrawFrame(GL10 gl) {
/*
* By default, OpenGL enables features that improve quality
* but reduce performance. One might want to tweak that
@@ -237,7 +238,7 @@
mLabels.draw(gl, tx, ty, labelId);
}
- public void sizeChanged(GL10 gl, int w, int h) {
+ public void onSurfaceChanged(GL10 gl, int w, int h) {
mWidth = w;
mHeight = h;
gl.glViewport(0, 0, w, h);
diff --git a/samples/ApiDemos/src/com/example/android/apis/text/Link.java b/samples/ApiDemos/src/com/example/android/apis/text/Link.java
index b8d83c2..b569d19 100644
--- a/samples/ApiDemos/src/com/example/android/apis/text/Link.java
+++ b/samples/ApiDemos/src/com/example/android/apis/text/Link.java
@@ -19,13 +19,66 @@
import com.example.android.apis.R;
import android.app.Activity;
+import android.graphics.Typeface;
import android.os.Bundle;
+import android.text.Html;
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.method.LinkMovementMethod;
+import android.text.style.StyleSpan;
+import android.text.style.URLSpan;
+import android.widget.TextView;
public class Link extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
+
setContentView(R.layout.link);
+
+ // text1 shows the android:autoLink property, which
+ // automatically linkifies things like URLs and phone numbers
+ // found in the text. No java code is needed to make this
+ // work.
+
+ // text2 has links specified by putting <a> tags in the string
+ // resource. By default these links will appear but not
+ // respond to user input. To make them active, you need to
+ // call setMovementMethod() on the TextView object.
+
+ TextView t2 = (TextView) findViewById(R.id.text2);
+ t2.setMovementMethod(LinkMovementMethod.getInstance());
+
+ // text3 shows creating text with links from HTML in the Java
+ // code, rather than from a string resource. Note that for a
+ // fixed string, using a (localizable) resource as shown above
+ // is usually a better way to go; this example is intended to
+ // illustrate how you might display text that came from a
+ // dynamic source (eg, the network).
+
+ TextView t3 = (TextView) findViewById(R.id.text3);
+ t3.setText(
+ Html.fromHtml(
+ "<b>text3:</b> Text with a " +
+ "<a href=\"http://www.google.com\">link</a> " +
+ "created in the Java source code using HTML."));
+ t3.setMovementMethod(LinkMovementMethod.getInstance());
+
+ // text4 illustrates constructing a styled string containing a
+ // link without using HTML at all. Again, for a fixed string
+ // you should probably be using a string resource, not a
+ // hardcoded value.
+
+ SpannableString ss = new SpannableString(
+ "text4: Click here to dial the phone.");
+
+ ss.setSpan(new StyleSpan(Typeface.BOLD), 0, 6,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ ss.setSpan(new URLSpan("tel:4155551212"), 13, 17,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+ TextView t4 = (TextView) findViewById(R.id.text4);
+ t4.setText(ss);
+ t4.setMovementMethod(LinkMovementMethod.getInstance());
}
}
diff --git a/samples/ApiDemos/src/com/example/android/apis/text/Marquee.java b/samples/ApiDemos/src/com/example/android/apis/text/Marquee.java
new file mode 100644
index 0000000..ba82ed6
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/text/Marquee.java
@@ -0,0 +1,31 @@
+/*
+ * 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.example.android.apis.text;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class Marquee extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.marquee);
+ }
+}
diff --git a/samples/ApiDemos/tests/src/com/example/android/apis/ApiDemosApplicationTests.java b/samples/ApiDemos/tests/src/com/example/android/apis/ApiDemosApplicationTests.java
index 97192e1..3074ca6 100644
--- a/samples/ApiDemos/tests/src/com/example/android/apis/ApiDemosApplicationTests.java
+++ b/samples/ApiDemos/tests/src/com/example/android/apis/ApiDemosApplicationTests.java
@@ -17,6 +17,8 @@
package com.example.android.apis;
import android.test.ApplicationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
/**
* This is a simple framework for a test of an Application. See
@@ -45,12 +47,14 @@
* explain any and all failures in other tests. This is not guaranteed
* to run before other tests, as junit uses reflection to find the tests.
*/
+ @SmallTest
public void testPreconditions() {
}
/**
* Test basic startup/shutdown of Application
*/
+ @MediumTest
public void testSimpleCreate() {
createApplication();
}
diff --git a/samples/ApiDemos/tests/src/com/example/android/apis/app/ForwardingTest.java b/samples/ApiDemos/tests/src/com/example/android/apis/app/ForwardingTest.java
index 5332fd5..340bedb 100644
--- a/samples/ApiDemos/tests/src/com/example/android/apis/app/ForwardingTest.java
+++ b/samples/ApiDemos/tests/src/com/example/android/apis/app/ForwardingTest.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.content.Intent;
import android.test.ActivityUnitTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
import android.widget.Button;
/**
@@ -68,6 +69,7 @@
* explain any and all failures in other tests. This is not guaranteed
* to run before other tests, as junit uses reflection to find the tests.
*/
+ @MediumTest
public void testPreconditions() {
startActivity(mStartIntent, null, null);
mButton = (Button) getActivity().findViewById(R.id.go);
@@ -80,6 +82,7 @@
* This test demonstrates examining the way that activity calls startActivity() to launch
* other activities.
*/
+ @MediumTest
public void testSubLaunch() {
Forwarding activity = startActivity(mStartIntent, null, null);
mButton = (Button) activity.findViewById(R.id.go);
@@ -95,6 +98,7 @@
/**
* This test demonstrates ways to exercise the Activity's life cycle.
*/
+ @MediumTest
public void testLifeCycleCreate() {
Forwarding activity = startActivity(mStartIntent, null, null);
diff --git a/samples/ApiDemos/tests/src/com/example/android/apis/app/LocalServiceTest.java b/samples/ApiDemos/tests/src/com/example/android/apis/app/LocalServiceTest.java
index 488a349..78fee41 100644
--- a/samples/ApiDemos/tests/src/com/example/android/apis/app/LocalServiceTest.java
+++ b/samples/ApiDemos/tests/src/com/example/android/apis/app/LocalServiceTest.java
@@ -24,6 +24,8 @@
import android.os.IBinder;
import android.test.MoreAsserts;
import android.test.ServiceTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
/**
* This is a simple framework for a test of a Service. See {@link android.test.ServiceTestCase
@@ -51,12 +53,14 @@
* explain any and all failures in other tests. This is not guaranteed
* to run before other tests, as junit uses reflection to find the tests.
*/
+ @SmallTest
public void testPreconditions() {
}
/**
* Test basic startup/shutdown of Service
*/
+ @SmallTest
public void testStartable() {
Intent startIntent = new Intent();
startIntent.setClass(getContext(), LocalService.class);
@@ -66,6 +70,7 @@
/**
* Test binding to service
*/
+ @MediumTest
public void testBindable() {
Intent startIntent = new Intent();
startIntent.setClass(getContext(), LocalService.class);
diff --git a/samples/ApiDemos/tests/src/com/example/android/apis/os/MorseCodeConverterTest.java b/samples/ApiDemos/tests/src/com/example/android/apis/os/MorseCodeConverterTest.java
index c16ae5a..7cf0395 100644
--- a/samples/ApiDemos/tests/src/com/example/android/apis/os/MorseCodeConverterTest.java
+++ b/samples/ApiDemos/tests/src/com/example/android/apis/os/MorseCodeConverterTest.java
@@ -17,6 +17,7 @@
package com.example.android.apis.os;
import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
/**
* An example of a true unit test that tests the utility class {@link MorseCodeConverter}.
@@ -28,6 +29,7 @@
*/
public class MorseCodeConverterTest extends TestCase {
+ @SmallTest
public void testCharacterS() throws Exception {
long[] expectedBeeps = {
diff --git a/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2ActivityTest.java b/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2ActivityTest.java
index 2e8c1cd..91f712f 100644
--- a/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2ActivityTest.java
+++ b/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2ActivityTest.java
@@ -19,6 +19,7 @@
import com.example.android.apis.R;
import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
import android.view.KeyEvent;
import android.widget.Button;
@@ -67,6 +68,7 @@
* explain any and all failures in other tests. This is not guaranteed
* to run before other tests, as junit uses reflection to find the tests.
*/
+ @MediumTest
public void testPreconditions() {
assertTrue("center button should be right of left button",
mLeftButton.getRight() < mCenterButton.getLeft());
@@ -75,11 +77,13 @@
assertTrue("left button should be focused", mLeftButton.isFocused());
}
+ @MediumTest
public void testGoingRightFromLeftButtonJumpsOverCenterToRight() {
sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
assertTrue("right button should be focused", mRightButton.isFocused());
}
+ @MediumTest
public void testGoingLeftFromRightButtonGoesToCenter() {
// Give right button focus by having it request focus. We post it
// to the UI thread because we are not running on the same thread, and
diff --git a/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2AndroidTest.java b/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2AndroidTest.java
index 8c9c8a5..b52e4b8 100644
--- a/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2AndroidTest.java
+++ b/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2AndroidTest.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
import android.view.FocusFinder;
import android.view.LayoutInflater;
import android.view.View;
@@ -87,6 +88,7 @@
* explain any and all failures in other tests. This is not guaranteed
* to run before other tests, as junit uses reflection to find the tests.
*/
+ @SmallTest
public void testPreconditions() {
assertNotNull(mLeftButton);
assertTrue("center button should be right of left button",
@@ -95,12 +97,14 @@
mCenterButton.getRight() < mRightButton.getLeft());
}
+ @SmallTest
public void testGoingRightFromLeftButtonJumpsOverCenterToRight() {
assertEquals("right should be next focus from left",
mRightButton,
mFocusFinder.findNextFocus(mRoot, mLeftButton, View.FOCUS_RIGHT));
}
+ @SmallTest
public void testGoingLeftFromRightButtonGoesToCenter() {
assertEquals("center should be next focus from right",
mCenterButton,
diff --git a/samples/Compass/Android.mk b/samples/Compass/Android.mk
new file mode 100644
index 0000000..9434582
--- /dev/null
+++ b/samples/Compass/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := Compass
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/samples/Compass/AndroidManifest.xml b/samples/Compass/AndroidManifest.xml
new file mode 100644
index 0000000..9aa5636
--- /dev/null
+++ b/samples/Compass/AndroidManifest.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- This file describes the code in the Compass package, which is
+ used by the system to determine how to start your application and
+ integrate it with the rest of the system. -->
+
+<!-- Declare the contents of this Android application. The namespace
+ attribute brings in the Android platform namespace, and the package
+ supplies a unique name for the application. When writing your
+ own application, the package name must be changed from "com.example.*"
+ to come from a domain that you own or have control over. -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.compass">
+
+ <!-- This package contains an application... The 'label' is the name
+ to display to the user for the overall application, and provides
+ a default label for all following components. The syntax here is a
+ reference to one of our string resources.-->
+ <application android:label="@string/compass_app">
+
+ <!-- An Activity in the application - this is something the user
+ can launch and interact with. The "name" attribute is the
+ name of the class within your package that implements this
+ activity. -->
+ <activity android:name="CompassActivity">
+
+ <!-- An IntentFilter tells the system when it should use your
+ activity. This allows the user to get to your activity
+ without someone having to explicitly know to launch your
+ class "com.example.android.compass_app.CompassActivity". -->
+ <intent-filter>
+ <!-- The MAIN action describes a main entry point into an
+ activity, without any associated data. -->
+ <action android:name="android.intent.action.MAIN" />
+
+ <!-- This places this activity into the main app list. -->
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+
+ </activity>
+
+ </application>
+
+</manifest>
diff --git a/samples/Compass/res/values/strings.xml b/samples/Compass/res/values/strings.xml
new file mode 100644
index 0000000..7cf3da4
--- /dev/null
+++ b/samples/Compass/res/values/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- This file contains resource definitions for displayed strings, allowing
+ them to be changed based on the locale and options. -->
+
+<resources>
+ <!-- Simple strings. -->
+ <string name="compass_app">Compass</string>
+</resources>
+
diff --git a/samples/Compass/src/com/example/android/compass/CompassActivity.java b/samples/Compass/src/com/example/android/compass/CompassActivity.java
new file mode 100644
index 0000000..c4b9566
--- /dev/null
+++ b/samples/Compass/src/com/example/android/compass/CompassActivity.java
@@ -0,0 +1,251 @@
+/*
+ * 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.example.android.compass;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+import static javax.microedition.khronos.opengles.GL10.*;
+
+import android.app.Activity;
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLSurfaceView.Renderer;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * This class provides a basic demonstration of how to use the
+ * {@link android.hardware.SensorManager SensorManager} API to draw
+ * a 3D compass.
+ */
+public class CompassActivity extends Activity implements Renderer, SensorEventListener {
+ private GLSurfaceView mGLSurfaceView;
+ private SensorManager mSensorManager;
+ private float[] mGData = new float[3];
+ private float[] mMData = new float[3];
+ private float[] mR = new float[16];
+ private float[] mI = new float[16];
+ private FloatBuffer mVertexBuffer;
+ private FloatBuffer mColorBuffer;
+ private ByteBuffer mIndexBuffer;
+ private float[] mOrientation = new float[3];
+ private int mCount;
+
+ public CompassActivity() {
+ }
+
+ /** Called with the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
+ mGLSurfaceView = new GLSurfaceView(this);
+ mGLSurfaceView.setRenderer(this);
+ setContentView(mGLSurfaceView);
+ }
+
+ @Override
+ protected void onResume() {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mGLSurfaceView.onResume();
+ Sensor gsensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+ Sensor msensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
+ mSensorManager.registerListener(this, gsensor, SensorManager.SENSOR_DELAY_GAME);
+ mSensorManager.registerListener(this, msensor, SensorManager.SENSOR_DELAY_GAME);
+ }
+
+ @Override
+ protected void onPause() {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ mGLSurfaceView.onPause();
+ mSensorManager.unregisterListener(this);
+ }
+
+ public int[] getConfigSpec() {
+ // We want a depth buffer, don't care about the
+ // details of the color buffer.
+ int[] configSpec = {
+ EGL10.EGL_DEPTH_SIZE, 16,
+ EGL10.EGL_NONE
+ };
+ return configSpec;
+ }
+
+ public void onDrawFrame(GL10 gl) {
+ /*
+ * Usually, the first thing one might want to do is to clear
+ * the screen. The most efficient way of doing this is to use
+ * glClear().
+ */
+
+ gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+
+ /*
+ * Now we're ready to draw some 3D objects
+ */
+
+ gl.glMatrixMode(GL10.GL_MODELVIEW);
+ gl.glLoadIdentity();
+ gl.glTranslatef(0, 0, -2);
+
+ /*
+ * All the magic happens here. The rotation matrix mR reported by
+ * SensorManager.getRotationMatrix() is a 4x4 row-major matrix.
+ * We need to use its inverse for rendering. The inverse is
+ * simply calculated by taking the matrix' transpose. However, since
+ * glMultMatrixf() expects a column-major matrix, we can use mR
+ * directly!
+ */
+ gl.glMultMatrixf(mR, 0);
+ // some test code which will be used/cleaned up before we ship this.
+ //gl.glMultMatrixf(mI, 0);
+
+ gl.glVertexPointer(3, GL_FLOAT, 0, mVertexBuffer);
+ gl.glColorPointer(4, GL_FLOAT, 0, mColorBuffer);
+ gl.glDrawElements(GL_LINES, 6, GL_UNSIGNED_BYTE, mIndexBuffer);
+ }
+
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
+ gl.glViewport(0, 0, width, height);
+
+ /*
+ * Set our projection matrix. This doesn't have to be done
+ * each time we draw, but usually a new projection needs to
+ * be set when the viewport is resized.
+ */
+
+ float ratio = (float) width / height;
+ gl.glMatrixMode(GL10.GL_PROJECTION);
+ gl.glLoadIdentity();
+ gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
+ }
+
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ /*
+ * By default, OpenGL enables features that improve quality
+ * but reduce performance. One might want to tweak that
+ * especially on software renderer.
+ */
+ gl.glDisable(GL10.GL_DITHER);
+
+ /*
+ * Some one-time OpenGL initialization can be made here
+ * probably based on features of this particular context
+ */
+ gl.glClearColor(1,1,1,1);
+ gl.glEnable(GL10.GL_CULL_FACE);
+ gl.glShadeModel(GL10.GL_SMOOTH);
+ gl.glEnable(GL10.GL_DEPTH_TEST);
+
+ /*
+ * create / load the our 3D models here
+ */
+
+ gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+ gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
+
+ float vertices[] = {
+ 0,0,0,
+ 1,0,0,
+ 0,1,0,
+ 0,0,1
+ };
+ float colors[] = {
+ 0,0,0,0,
+ 1,0,0,1,
+ 0,1,0,1,
+ 0,0,1,1
+ };
+ byte indices[] = { 0, 1, 0, 2, 0, 3 };
+
+ // Buffers to be passed to gl*Pointer() functions
+ // must be direct, i.e., they must be placed on the
+ // native heap where the garbage collector cannot
+ // move them.
+ //
+ // Buffers with multi-byte datatypes (e.g., short, int, float)
+ // must have their byte order set to native order
+
+ ByteBuffer vbb;
+ vbb = ByteBuffer.allocateDirect(vertices.length*4);
+ vbb.order(ByteOrder.nativeOrder());
+ mVertexBuffer = vbb.asFloatBuffer();
+ mVertexBuffer.put(vertices);
+ mVertexBuffer.position(0);
+
+ vbb = ByteBuffer.allocateDirect(colors.length*4);
+ vbb.order(ByteOrder.nativeOrder());
+ mColorBuffer = vbb.asFloatBuffer();
+ mColorBuffer.put(colors);
+ mColorBuffer.position(0);
+
+ mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
+ mIndexBuffer.put(indices);
+ mIndexBuffer.position(0);
+ }
+
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ }
+
+ public void onSensorChanged(SensorEvent event) {
+ int type = event.sensor.getType();
+ float[] data;
+ if (type == Sensor.TYPE_ACCELEROMETER) {
+ data = mGData;
+ } else if (type == Sensor.TYPE_MAGNETIC_FIELD) {
+ data = mMData;
+ } else {
+ // we should not be here.
+ return;
+ }
+ for (int i=0 ; i<3 ; i++)
+ data[i] = event.values[i];
+
+ SensorManager.getRotationMatrix(mR, mI, mGData, mMData);
+// some test code which will be used/cleaned up before we ship this.
+// SensorManager.remapCoordinateSystem(mR,
+// SensorManager.AXIS_X, SensorManager.AXIS_Z, mR);
+// SensorManager.remapCoordinateSystem(mR,
+// SensorManager.AXIS_Y, SensorManager.AXIS_MINUS_X, mR);
+ SensorManager.getOrientation(mR, mOrientation);
+ float incl = SensorManager.getInclination(mI);
+
+ if (mCount++ > 50) {
+ final float rad2deg = (float)(180.0f/Math.PI);
+ mCount = 0;
+ Log.d("Compass", "yaw: " + (int)(mOrientation[0]*rad2deg) +
+ " pitch: " + (int)(mOrientation[1]*rad2deg) +
+ " roll: " + (int)(mOrientation[2]*rad2deg) +
+ " incl: " + (int)(incl*rad2deg)
+ );
+ }
+ }
+}
diff --git a/samples/GlobalTime/src/com/android/globaltime/Clock.java b/samples/GlobalTime/src/com/android/globaltime/Clock.java
index 4b6c0f7..9aad71a 100644
--- a/samples/GlobalTime/src/com/android/globaltime/Clock.java
+++ b/samples/GlobalTime/src/com/android/globaltime/Clock.java
@@ -24,7 +24,7 @@
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
-import android.pim.DateUtils;
+import android.text.format.DateUtils;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
diff --git a/samples/HelloActivity/tests/AndroidManifest.xml b/samples/HelloActivity/tests/AndroidManifest.xml
index 29b3a9a..5294d07 100644
--- a/samples/HelloActivity/tests/AndroidManifest.xml
+++ b/samples/HelloActivity/tests/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.helloactivity.tests">
+ package="com.example.android.helloactivity.tests">
<!-- We add an application tag here just so that we can indicate that
this package needs to link against the android.test library,
diff --git a/samples/HelloActivity/tests/src/com/android/helloactivity/HelloActivityTest.java b/samples/HelloActivity/tests/src/com/example/android/helloactivity/HelloActivityTest.java
similarity index 95%
rename from samples/HelloActivity/tests/src/com/android/helloactivity/HelloActivityTest.java
rename to samples/HelloActivity/tests/src/com/example/android/helloactivity/HelloActivityTest.java
index 76eecf2..6e032da 100644
--- a/samples/HelloActivity/tests/src/com/android/helloactivity/HelloActivityTest.java
+++ b/samples/HelloActivity/tests/src/com/example/android/helloactivity/HelloActivityTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.helloactivity;
+package com.example.android.helloactivity;
import android.test.ActivityInstrumentationTestCase;
diff --git a/samples/Home/res/values-cs/strings.xml b/samples/Home/res/values-cs/strings.xml
index 6d91727..2830534 100644
--- a/samples/Home/res/values-cs/strings.xml
+++ b/samples/Home/res/values-cs/strings.xml
@@ -1,10 +1,11 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="home_title">Domů</string>
- <string name="menu_notifications">Oznámení</string>
- <string name="menu_search">Hledat</string>
- <string name="menu_wallpaper">Tapeta</string>
- <string name="show_all_apps">Vše</string>
- <string name="wallpaper_instructions">Klepnutím na obrázek nastavíte tapetu portrétu</string>
+ <string name="home_title">"Domů"</string>
+ <string name="show_all_apps">"Vše"</string>
+ <string name="menu_wallpaper">"Tapeta"</string>
+ <string name="menu_search">"Hledat"</string>
+ <!-- no translation found for menu_settings (1769059051084007158) -->
+ <skip />
+ <string name="wallpaper_instructions">"Klepnutím na obrázek nastavíte tapetu portrétu"</string>
</resources>
diff --git a/samples/Home/res/values-de-rDE/strings.xml b/samples/Home/res/values-de-rDE/strings.xml
index aa5c4c1..28a1b7c 100644
--- a/samples/Home/res/values-de-rDE/strings.xml
+++ b/samples/Home/res/values-de-rDE/strings.xml
@@ -1,10 +1,11 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="home_title">Startseite</string>
- <string name="menu_notifications">Benachrichtigungen</string>
- <string name="menu_search">Suchen</string>
- <string name="menu_wallpaper">Bildschirmhintergrund</string>
- <string name="show_all_apps">Alle</string>
- <string name="wallpaper_instructions">Tippen Sie auf Bild, um Porträt-Bildschirmhintergrund einzustellen</string>
+ <string name="home_title">"Startseite"</string>
+ <string name="show_all_apps">"Alle"</string>
+ <string name="menu_wallpaper">"Bildschirmhintergrund"</string>
+ <string name="menu_search">"Suchen"</string>
+ <!-- no translation found for menu_settings (1769059051084007158) -->
+ <skip />
+ <string name="wallpaper_instructions">"Tippen Sie auf Bild, um Porträt-Bildschirmhintergrund einzustellen"</string>
</resources>
diff --git a/samples/Home/res/values-es-rUS/strings.xml b/samples/Home/res/values-es-rUS/strings.xml
index a0a5657..63252cc 100644
--- a/samples/Home/res/values-es-rUS/strings.xml
+++ b/samples/Home/res/values-es-rUS/strings.xml
@@ -1,10 +1,11 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="home_title">Casa</string>
- <string name="menu_notifications">Notificaciones</string>
- <string name="menu_search">Búsqueda</string>
- <string name="menu_wallpaper">Papel tapiz</string>
- <string name="show_all_apps">Todo</string>
- <string name="wallpaper_instructions">Puntee en la imagen para establecer papel tapiz vertical</string>
+ <string name="home_title">"Casa"</string>
+ <string name="show_all_apps">"Todo"</string>
+ <string name="menu_wallpaper">"Papel tapiz"</string>
+ <string name="menu_search">"Búsqueda"</string>
+ <!-- no translation found for menu_settings (1769059051084007158) -->
+ <skip />
+ <string name="wallpaper_instructions">"Puntee en la imagen para establecer papel tapiz vertical"</string>
</resources>
diff --git a/samples/Home/res/values-nl-rNL/strings.xml b/samples/Home/res/values-nl-rNL/strings.xml
index 9e3a49d..4a5ae4f 100644
--- a/samples/Home/res/values-nl-rNL/strings.xml
+++ b/samples/Home/res/values-nl-rNL/strings.xml
@@ -1,10 +1,11 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="home_title">Start</string>
- <string name="menu_notifications">Meldingen</string>
- <string name="menu_search">Zoeken</string>
- <string name="menu_wallpaper">Achtergrond</string>
- <string name="show_all_apps">Alles</string>
- <string name="wallpaper_instructions">Tik op afbeelding om portretachtergrond in te stellen</string>
+ <string name="home_title">"Start"</string>
+ <string name="show_all_apps">"Alles"</string>
+ <string name="menu_wallpaper">"Achtergrond"</string>
+ <string name="menu_search">"Zoeken"</string>
+ <!-- no translation found for menu_settings (1769059051084007158) -->
+ <skip />
+ <string name="wallpaper_instructions">"Tik op afbeelding om portretachtergrond in te stellen"</string>
</resources>
diff --git a/samples/LunarLander/tests/AndroidManifest.xml b/samples/LunarLander/tests/AndroidManifest.xml
index 656e302..1bc8364 100644
--- a/samples/LunarLander/tests/AndroidManifest.xml
+++ b/samples/LunarLander/tests/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.lunarlander.tests">
+ package="com.example.android.lunarlander.tests">
<!-- We add an application tag here just so that we can indicate that
this package needs to link against the android.test library,
diff --git a/samples/LunarLander/tests/src/com/android/lunarlander/LunarLanderTest.java b/samples/LunarLander/tests/src/com/example/android/lunarlander/LunarLanderTest.java
similarity index 96%
rename from samples/LunarLander/tests/src/com/android/lunarlander/LunarLanderTest.java
rename to samples/LunarLander/tests/src/com/example/android/lunarlander/LunarLanderTest.java
index ce9d5f8..fae02da 100644
--- a/samples/LunarLander/tests/src/com/android/lunarlander/LunarLanderTest.java
+++ b/samples/LunarLander/tests/src/com/example/android/lunarlander/LunarLanderTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.lunarlander;
+package com.example.android.lunarlander;
import android.test.ActivityInstrumentationTestCase;
diff --git a/samples/NotePad/AndroidManifest.xml b/samples/NotePad/AndroidManifest.xml
index 2dd675b..84e87dd 100644
--- a/samples/NotePad/AndroidManifest.xml
+++ b/samples/NotePad/AndroidManifest.xml
@@ -51,6 +51,8 @@
<activity android:name="NoteEditor"
android:theme="@android:style/Theme.Light"
android:label="@string/title_note"
+ android:screenOrientation="sensor"
+ android:configChanges="keyboardHidden|orientation"
>
<!-- This filter says that we can view or edit the data of
a single note -->
diff --git a/samples/NotePad/res/layout/note_editor.xml b/samples/NotePad/res/layout/note_editor.xml
index dba55a1..c54a963 100644
--- a/samples/NotePad/res/layout/note_editor.xml
+++ b/samples/NotePad/res/layout/note_editor.xml
@@ -24,5 +24,6 @@
android:scrollbars="vertical"
android:fadingEdge="vertical"
android:gravity="top"
+ android:textSize="22sp"
android:capitalize="sentences"
/>
diff --git a/samples/NotePad/src/com/google/provider/NotePad.java b/samples/NotePad/src/com/google/provider/NotePad.java
new file mode 100644
index 0000000..f8de69b
--- /dev/null
+++ b/samples/NotePad/src/com/google/provider/NotePad.java
@@ -0,0 +1,65 @@
+/*
+ * 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.google.provider;
+
+import android.net.Uri;
+import android.provider.BaseColumns;
+
+/**
+ * Convenience definitions for NotePadProvider
+ */
+public final class NotePad {
+ /**
+ * Notes table
+ */
+ public static final class Notes implements BaseColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI
+ = Uri.parse("content://com.google.provider.NotePad/notes");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "modified DESC";
+
+ /**
+ * The title of the note
+ * <P>Type: TEXT</P>
+ */
+ public static final String TITLE = "title";
+
+ /**
+ * The note itself
+ * <P>Type: TEXT</P>
+ */
+ public static final String NOTE = "note";
+
+ /**
+ * The timestamp for when the note was created
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String CREATED_DATE = "created";
+
+ /**
+ * The timestamp for when the note was last modified
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String MODIFIED_DATE = "modified";
+ }
+}
diff --git a/samples/NotePad/tests/AndroidManifest.xml b/samples/NotePad/tests/AndroidManifest.xml
index fc6c1cd..afd502b 100644
--- a/samples/NotePad/tests/AndroidManifest.xml
+++ b/samples/NotePad/tests/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.notepad.tests">
+ package="com.example.android.notepad.tests">
<!-- We add an application tag here just so that we can indicate that
this package needs to link against the android.test library,
diff --git a/samples/NotePad/tests/src/com/android/notepad/NotePadTest.java b/samples/NotePad/tests/src/com/example/android/notepad/NotePadTest.java
similarity index 96%
rename from samples/NotePad/tests/src/com/android/notepad/NotePadTest.java
rename to samples/NotePad/tests/src/com/example/android/notepad/NotePadTest.java
index 48fc264..452c599 100644
--- a/samples/NotePad/tests/src/com/android/notepad/NotePadTest.java
+++ b/samples/NotePad/tests/src/com/example/android/notepad/NotePadTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.notepad;
+package com.example.android.notepad;
import android.test.ActivityInstrumentationTestCase;
diff --git a/samples/PlatformLibrary/Android.mk b/samples/PlatformLibrary/Android.mk
new file mode 100644
index 0000000..d700386
--- /dev/null
+++ b/samples/PlatformLibrary/Android.mk
@@ -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.
+#
+
+# This makefile shows how to build your own shared library that can be
+# shipped on the system of a phone, and included additional examples of
+# including JNI code with the library and writing client applications against it.
+
+LOCAL_PATH := $(call my-dir)
+
+# the library
+# ============================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+# This is the target being built.
+LOCAL_MODULE:= com.example.android.platform_library
+
+# Only compile source java files for the platform library.
+LOCAL_SRC_FILES := $(call all-java-files-under, java)
+
+include $(BUILD_JAVA_LIBRARY)
+
+# ============================================================
+
+# Also build all of the sub-targets under this one: the library's
+# associated JNI code, and a sample client of the library.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/samples/PlatformLibrary/README.txt b/samples/PlatformLibrary/README.txt
new file mode 100644
index 0000000..e2a7c80
--- /dev/null
+++ b/samples/PlatformLibrary/README.txt
@@ -0,0 +1,78 @@
+Platform Library Example
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+This directory contains a full example of writing your own Android platform
+shared library, without changing the Android framework. It also shows how to
+write JNI code for incorporating native code into the library, and a client
+application that uses the library.
+
+This example is ONLY for people working with the open source platform to
+create a system image that will be delivered on a device which will include
+a custom library as shown here. It can not be used to create a third party
+shared library, which is not currently supported in Android.
+
+Note that while this example is almost entirely self-contained -- you can
+build it and run the client app without any changes to the framework -- there
+is one change you must make so that the system will recognize your library:
+
+In frameworks/base/data/etc/permissions.xml is a list of all of the optional
+shared libraries available in the system. You will need to add an entry at
+the bottom of this file for your own shared library, which looks like this
+for our sample code here:
+
+ <library name="com.example.android.platform_library"
+ file="/system/framework/com.example.android.platform_library.jar"/>
+
+
+There are three major parts of this example, supplying three distinct
+build targets and corresponding build outputs:
+
+
+com.example.android.platform_library
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The top-level Android.mk defines the rules to build the shared library itself,
+whose target is "com.example.android.platform_library". The code for this
+library lives under java/.
+
+Note that the product for this library is a raw .jar file, NOT a .apk, which
+means there is no manifest or resources associated with the library.
+Unfortunately this means that if you need any resources for the library, such
+as drawables or layout files, you will need to add these to the core framework
+resources under frameworks/base/res. Please make sure when doing this that
+you do not make any of these resources public, they should not become part of
+the Android API. In the future we will allow shared libraries to have their
+own resources.
+
+Other than that, the library is very straight-forward, and you can write
+basically whatever code you want. You can also put code in other Java
+namespaces -- the namespace given in the <library> tag above is just the
+public unique name by which clients will link to your library, but once this
+link happens all of the Java namespaces in that library will be available
+to the client.
+
+
+libplatform_library_jni
+~~~~~~~~~~~~~~~~~~~~~~~
+
+This is an optional example of how to write JNI code associated with a
+shared library. This code lives under jni/. The jni/Android.mk file defines
+the rules for building the final .so in which the code lives. This example
+provides everything needed to hook up the native code with the Java library
+and call through to it, plus a very simple JNI call.
+
+
+PlatformLibraryClient
+~~~~~~~~~~~~~~~~~~~~~
+
+This shows an example of how you can write client applications for your new
+shared library. This code lives under client/. Note that the example is
+simply a regular Android .apk, like all of the other .apks created by the
+build system. The only two special things needed to use your library are:
+
+- A LOCAL_JAVA_LIBRARIES line in the Android.mk to have the build system link
+against your shared library.
+
+- A <uses-library> line in the AndroidManifest.xml to have the runtime load
+your library into the application.
diff --git a/samples/PlatformLibrary/client/Android.mk b/samples/PlatformLibrary/client/Android.mk
new file mode 100644
index 0000000..cfd5493
--- /dev/null
+++ b/samples/PlatformLibrary/client/Android.mk
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+
+# This makefile is an example of writing an application that will link against
+# a custom shared library included with an Android system.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+# This is the target being built.
+LOCAL_PACKAGE_NAME := PlatformLibraryClient
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Link against the current Android SDK.
+LOCAL_SDK_VERSION := current
+
+# Also link against our own custom library.
+LOCAL_JAVA_LIBRARIES := com.example.android.platform_library
+
+include $(BUILD_PACKAGE)
diff --git a/samples/PlatformLibrary/client/AndroidManifest.xml b/samples/PlatformLibrary/client/AndroidManifest.xml
new file mode 100644
index 0000000..be0d9a1
--- /dev/null
+++ b/samples/PlatformLibrary/client/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- This is an example of writing a client application for a custom
+ platform library. -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.platform_library.client">
+
+ <application android:label="Platform Lib Client">
+
+ <!-- This tells the system about the custom library used by the
+ application, so that it can be properly loaded and linked
+ to the app when the app is initialized. -->
+ <uses-library android:name="com.example.android.platform_library" />
+
+ <activity android:name="Client">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/samples/PlatformLibrary/client/src/com/example/android/platform_library/client/Client.java b/samples/PlatformLibrary/client/src/com/example/android/platform_library/client/Client.java
new file mode 100644
index 0000000..8722c72
--- /dev/null
+++ b/samples/PlatformLibrary/client/src/com/example/android/platform_library/client/Client.java
@@ -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.example.android.platform_library.client;
+
+import com.example.android.platform_library.PlatformLibrary;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+/**
+ * Use a custom platform library.
+ */
+public class Client extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Call an API on the library.
+ PlatformLibrary pl = new PlatformLibrary();
+ int res = pl.getInt(false);
+
+ // We'll just make our own view to show the result.
+ TextView tv = new TextView(this);
+ tv.setText("Got from lib: " + res);
+ setContentView(tv);
+ }
+}
+
diff --git a/samples/PlatformLibrary/java/com/example/android/platform_library/PlatformLibrary.java b/samples/PlatformLibrary/java/com/example/android/platform_library/PlatformLibrary.java
new file mode 100644
index 0000000..68154ec
--- /dev/null
+++ b/samples/PlatformLibrary/java/com/example/android/platform_library/PlatformLibrary.java
@@ -0,0 +1,67 @@
+/*
+ * 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.example.android.platform_library;
+
+import android.util.Config;
+import android.util.Log;
+
+public final class PlatformLibrary {
+ static {
+ /*
+ * Load the library. If it's already loaded, this does nothing.
+ */
+ System.loadLibrary("platform_library_jni");
+ }
+
+ private int mJniInt = -1;
+
+ public PlatformLibrary() {}
+
+ /*
+ * Test native methods.
+ */
+ public int getInt(boolean bad) {
+ /* this alters mJniInt */
+ int result = getJniInt(bad);
+
+ /* reverse a string, for no very good reason */
+ String reverse = reverseString("Android!");
+
+ Log.i("PlatformLibrary", "getInt: " + result + ", '" + reverse + "'");
+
+ return mJniInt;
+ }
+
+ /*
+ * Simple method, called from native code.
+ */
+ private static void yodel(String msg) {
+ Log.d("PlatformLibrary", "yodel: " + msg);
+ }
+
+ /*
+ * Trivial native method call. If "bad" is true, this will throw an
+ * exception.
+ */
+ native private int getJniInt(boolean bad);
+
+ /*
+ * Native method that returns a new string that is the reverse of
+ * the original. This also calls yodel().
+ */
+ native private static String reverseString(String str);
+}
diff --git a/samples/PlatformLibrary/jni/Android.mk b/samples/PlatformLibrary/jni/Android.mk
new file mode 100644
index 0000000..1bdefa1
--- /dev/null
+++ b/samples/PlatformLibrary/jni/Android.mk
@@ -0,0 +1,53 @@
+#
+# 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.
+#
+
+# This makefile supplies the rules for building a library of JNI code for
+# use by our example platform shared library.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+# This is the target being built.
+LOCAL_MODULE:= libplatform_library_jni
+
+# All of the source files that we will compile.
+LOCAL_SRC_FILES:= \
+ PlatformLibrary.cpp
+
+# All of the shared libraries we link against.
+LOCAL_SHARED_LIBRARIES := \
+ libandroid_runtime \
+ libnativehelper \
+ libcutils \
+ libutils
+
+# No static libraries.
+LOCAL_STATIC_LIBRARIES :=
+
+# Also need the JNI headers.
+LOCAL_C_INCLUDES += \
+ $(JNI_H_INCLUDE)
+
+# No specia compiler flags.
+LOCAL_CFLAGS +=
+
+# Don't prelink this library. For more efficient code, you may want
+# to add this library to the prelink map and set this to true.
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/samples/PlatformLibrary/jni/PlatformLibrary.cpp b/samples/PlatformLibrary/jni/PlatformLibrary.cpp
new file mode 100644
index 0000000..ad60002
--- /dev/null
+++ b/samples/PlatformLibrary/jni/PlatformLibrary.cpp
@@ -0,0 +1,273 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "PlatformLibrary"
+#include "utils/Log.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include "jni.h"
+
+
+// ----------------------------------------------------------------------------
+
+/*
+ * Field/method IDs and class object references.
+ *
+ * You should not need to store the JNIEnv pointer in here. It is
+ * thread-specific and will be passed back in on every call.
+ */
+static struct {
+ jclass platformLibraryClass;
+ jfieldID jniInt;
+ jmethodID yodel;
+} gCachedState;
+
+// ----------------------------------------------------------------------------
+
+/*
+ * Helper function to throw an arbitrary exception.
+ *
+ * Takes the exception class name, a format string, and one optional integer
+ * argument (useful for including an error code, perhaps from errno).
+ */
+static void throwException(JNIEnv* env, const char* ex, const char* fmt,
+ int data) {
+
+ if (jclass cls = env->FindClass(ex)) {
+ if (fmt != NULL) {
+ char msg[1000];
+ snprintf(msg, sizeof(msg), fmt, data);
+ env->ThrowNew(cls, msg);
+ } else {
+ env->ThrowNew(cls, NULL);
+ }
+
+ /*
+ * This is usually not necessary -- local references are released
+ * automatically when the native code returns to the VM. It's
+ * required if the code doesn't actually return, e.g. it's sitting
+ * in a native event loop.
+ */
+ env->DeleteLocalRef(cls);
+ }
+}
+
+/*
+ * Trivial sample method.
+ *
+ * If "bad" is true, this throws an exception. Otherwise, this sets the
+ * "mJniInt" field to 42 and returns 24.
+ */
+static jint PlatformLibrary_getJniInt(JNIEnv* env, jobject thiz, jboolean bad) {
+ if (bad) {
+ throwException(env, "java/lang/IllegalStateException",
+ "you are bad", 0);
+ return 0; /* return value will be ignored */
+ }
+ env->SetIntField(thiz, gCachedState.jniInt, 42);
+ return (jint)24;
+}
+
+/*
+ * A more complex sample method.
+ *
+ * This takes a String as an argument, and returns a new String with
+ * characters in reverse order. The new string is passed to another method.
+ * This demonstrates basic String manipulation functions and method
+ * invocation.
+ *
+ * This method is declared "static", so there's no "this" pointer; instead,
+ * we get a pointer to the class object.
+ */
+static jstring PlatformLibrary_reverseString(JNIEnv* env, jclass clazz,
+ jstring str) {
+
+ if (str == NULL) {
+ throwException(env, "java/lang/NullPointerException", NULL, 0);
+ return NULL;
+ }
+
+ /*
+ * Get a pointer to the string's UTF-16 character data. The data
+ * may be a copy or a pointer to the original. Since String data
+ * is immutable, we're not allowed to touch it.
+ */
+ const jchar* strChars = env->GetStringChars(str, NULL);
+ if (strChars == NULL) {
+ /* something went wrong */
+ LOGW("Couldn't get string chars\n");
+ return NULL;
+ }
+ jsize strLength = env->GetStringLength(str);
+
+ /*
+ * Write a progress message to the log. Log messages are UTF-8, so
+ * we want to convert the string to show it.
+ */
+ const char* printable = env->GetStringUTFChars(str, NULL);
+ if (printable != NULL) {
+ LOGD("Reversing string '%s'\n", printable);
+ env->ReleaseStringUTFChars(str, printable);
+ }
+
+ /*
+ * Copy the characters to temporary storage, reversing as we go.
+ */
+ jchar tempChars[strLength];
+ for (int i = 0; i < strLength; i++) {
+ tempChars[i] = strChars[strLength -1 -i];
+ }
+
+ /*
+ * Release the original String. That way, if something fails later on,
+ * we don't have to worry about this leading to a memory leak.
+ */
+ env->ReleaseStringChars(str, strChars);
+ strChars = NULL; /* this pointer no longer valid */
+
+ /*
+ * Create a new String with the chars.
+ */
+ jstring result = env->NewString(tempChars, strLength);
+ if (result == NULL) {
+ LOGE("NewString failed\n");
+ return NULL;
+ }
+
+ /*
+ * Now let's do something with it. We already have the methodID for
+ * "yodel", so we can invoke it directly. It's in our class, so we
+ * can use the Class object reference that was passed in.
+ */
+ env->CallStaticVoidMethod(clazz, gCachedState.yodel, result);
+
+ return result;
+}
+
+
+// ----------------------------------------------------------------------------
+
+/*
+ * Array of methods.
+ *
+ * Each entry has three fields: the name of the method, the method
+ * signature, and a pointer to the native implementation.
+ */
+static const JNINativeMethod gMethods[] = {
+ { "getJniInt", "(Z)I",
+ (void*)PlatformLibrary_getJniInt },
+ { "reverseString", "(Ljava/lang/String;)Ljava/lang/String;",
+ (void*)PlatformLibrary_reverseString },
+};
+
+/*
+ * Do some (slow-ish) lookups now and save the results.
+ *
+ * Returns 0 on success.
+ */
+static int cacheIds(JNIEnv* env, jclass clazz) {
+ /*
+ * Save the class in case we want to use it later. Because this is a
+ * reference to the Class object, we need to convert it to a JNI global
+ * reference.
+ */
+ gCachedState.platformLibraryClass = (jclass) env->NewGlobalRef(clazz);
+ if (clazz == NULL) {
+ LOGE("Can't create new global ref\n");
+ return -1;
+ }
+
+ /*
+ * Cache field and method IDs. IDs are not references, which means we
+ * don't need to call NewGlobalRef on them.
+ */
+ gCachedState.jniInt = env->GetFieldID(clazz, "mJniInt", "I");
+ if (gCachedState.jniInt == NULL) {
+ LOGE("Can't find PlatformLibrary.mJniInt\n");
+ return -1;
+ }
+
+ gCachedState.yodel = env->GetStaticMethodID(clazz, "yodel",
+ "(Ljava/lang/String;)V");
+ if (gCachedState.yodel == NULL) {
+ LOGE("Can't find PlatformLibrary.yodel\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Explicitly register all methods for our class.
+ *
+ * While we're at it, cache some class references and method/field IDs.
+ *
+ * Returns 0 on success.
+ */
+static int registerMethods(JNIEnv* env) {
+ static const char* const kClassName =
+ "com/example/android/platform_library/PlatformLibrary";
+ jclass clazz;
+
+ /* look up the class */
+ clazz = env->FindClass(kClassName);
+ if (clazz == NULL) {
+ LOGE("Can't find class %s\n", kClassName);
+ return -1;
+ }
+
+ /* register all the methods */
+ if (env->RegisterNatives(clazz, gMethods,
+ sizeof(gMethods) / sizeof(gMethods[0])) != JNI_OK)
+ {
+ LOGE("Failed registering methods for %s\n", kClassName);
+ return -1;
+ }
+
+ /* fill out the rest of the ID cache */
+ return cacheIds(env, clazz);
+}
+
+// ----------------------------------------------------------------------------
+
+/*
+ * This is called by the VM when the shared library is first loaded.
+ */
+jint JNI_OnLoad(JavaVM* vm, void* reserved) {
+ JNIEnv* env = NULL;
+ jint result = -1;
+
+ if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
+ LOGE("ERROR: GetEnv failed\n");
+ goto bail;
+ }
+ assert(env != NULL);
+
+ if (registerMethods(env) != 0) {
+ LOGE("ERROR: PlatformLibrary native registration failed\n");
+ goto bail;
+ }
+
+ /* success -- return valid version number */
+ result = JNI_VERSION_1_4;
+
+bail:
+ return result;
+}
diff --git a/samples/SkeletonApp/tests/AndroidManifest.xml b/samples/SkeletonApp/tests/AndroidManifest.xml
index 2a6a7d6..fac1f41 100644
--- a/samples/SkeletonApp/tests/AndroidManifest.xml
+++ b/samples/SkeletonApp/tests/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.skeletonapp.tests">
+ package="com.example.android.skeletonapp.tests">
<!-- We add an application tag here just so that we can indicate that
this package needs to link against the android.test library,
diff --git a/samples/SkeletonApp/tests/src/com/android/skeletonapp/SkeletonAppTest.java b/samples/SkeletonApp/tests/src/com/example/android/skeletonapp/SkeletonAppTest.java
similarity index 96%
rename from samples/SkeletonApp/tests/src/com/android/skeletonapp/SkeletonAppTest.java
rename to samples/SkeletonApp/tests/src/com/example/android/skeletonapp/SkeletonAppTest.java
index 58518e2..3123348 100644
--- a/samples/SkeletonApp/tests/src/com/android/skeletonapp/SkeletonAppTest.java
+++ b/samples/SkeletonApp/tests/src/com/example/android/skeletonapp/SkeletonAppTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.skeletonapp;
+package com.example.android.skeletonapp;
import android.test.ActivityInstrumentationTestCase;
diff --git a/samples/Snake/tests/AndroidManifest.xml b/samples/Snake/tests/AndroidManifest.xml
index 63eadf4..382506c 100644
--- a/samples/Snake/tests/AndroidManifest.xml
+++ b/samples/Snake/tests/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.snake.tests">
+ package="com.example.android.snake.tests">
<!-- We add an application tag here just so that we can indicate that
this package needs to link against the android.test library,
diff --git a/samples/Snake/tests/src/com/android/snake/SnakeTest.java b/samples/Snake/tests/src/com/example/android/snake/SnakeTest.java
similarity index 96%
rename from samples/Snake/tests/src/com/android/snake/SnakeTest.java
rename to samples/Snake/tests/src/com/example/android/snake/SnakeTest.java
index 554bdbf..35d1b12 100644
--- a/samples/Snake/tests/src/com/android/snake/SnakeTest.java
+++ b/samples/Snake/tests/src/com/example/android/snake/SnakeTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.snake;
+package com.example.android.snake;
import android.test.ActivityInstrumentationTestCase;
diff --git a/samples/SoftKeyboard/Android.mk b/samples/SoftKeyboard/Android.mk
new file mode 100755
index 0000000..dfd546e
--- /dev/null
+++ b/samples/SoftKeyboard/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := eng samples
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_PACKAGE_NAME := SoftKeyboard
+
+include $(BUILD_PACKAGE)
diff --git a/samples/SoftKeyboard/AndroidManifest.xml b/samples/SoftKeyboard/AndroidManifest.xml
new file mode 100755
index 0000000..61b5131
--- /dev/null
+++ b/samples/SoftKeyboard/AndroidManifest.xml
@@ -0,0 +1,12 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.softkeyboard">
+ <application android:label="@string/ime_name">
+ <service android:name="SoftKeyboard"
+ android:permission="android.permission.BIND_INPUT_METHOD">
+ <intent-filter>
+ <action android:name="android.view.InputMethod" />
+ </intent-filter>
+ <meta-data android:name="android.view.im" android:resource="@xml/method" />
+ </service>
+ </application>
+</manifest>
diff --git a/samples/SoftKeyboard/res/drawable/sym_keyboard_delete.png b/samples/SoftKeyboard/res/drawable/sym_keyboard_delete.png
new file mode 100644
index 0000000..6cee596
--- /dev/null
+++ b/samples/SoftKeyboard/res/drawable/sym_keyboard_delete.png
Binary files differ
diff --git a/samples/SoftKeyboard/res/drawable/sym_keyboard_done.png b/samples/SoftKeyboard/res/drawable/sym_keyboard_done.png
new file mode 100755
index 0000000..c0d6d13
--- /dev/null
+++ b/samples/SoftKeyboard/res/drawable/sym_keyboard_done.png
Binary files differ
diff --git a/samples/SoftKeyboard/res/drawable/sym_keyboard_return.png b/samples/SoftKeyboard/res/drawable/sym_keyboard_return.png
new file mode 100644
index 0000000..cbe2b15
--- /dev/null
+++ b/samples/SoftKeyboard/res/drawable/sym_keyboard_return.png
Binary files differ
diff --git a/samples/SoftKeyboard/res/drawable/sym_keyboard_shift.png b/samples/SoftKeyboard/res/drawable/sym_keyboard_shift.png
new file mode 100644
index 0000000..d059628
--- /dev/null
+++ b/samples/SoftKeyboard/res/drawable/sym_keyboard_shift.png
Binary files differ
diff --git a/samples/SoftKeyboard/res/drawable/sym_keyboard_space.png b/samples/SoftKeyboard/res/drawable/sym_keyboard_space.png
new file mode 100644
index 0000000..09b94d9
--- /dev/null
+++ b/samples/SoftKeyboard/res/drawable/sym_keyboard_space.png
Binary files differ
diff --git a/samples/SoftKeyboard/res/layout/input.xml b/samples/SoftKeyboard/res/layout/input.xml
new file mode 100755
index 0000000..1b57468
--- /dev/null
+++ b/samples/SoftKeyboard/res/layout/input.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<com.example.android.softkeyboard.LatinKeyboardView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/keyboard"
+ android:layout_alignParentBottom="true"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ />
diff --git a/samples/SoftKeyboard/res/values-land/dimens.xml b/samples/SoftKeyboard/res/values-land/dimens.xml
new file mode 100644
index 0000000..1929ae0
--- /dev/null
+++ b/samples/SoftKeyboard/res/values-land/dimens.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<resources>
+ <dimen name="key_height">46px</dimen>
+</resources>
\ No newline at end of file
diff --git a/samples/SoftKeyboard/res/values/colors.xml b/samples/SoftKeyboard/res/values/colors.xml
new file mode 100644
index 0000000..74d103a
--- /dev/null
+++ b/samples/SoftKeyboard/res/values/colors.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+<resources>
+ <color name="candidate_normal">#FF000000</color>
+ <color name="candidate_recommended">#FFE35900</color>
+ <color name="candidate_other">#ff808080</color>
+ <color name="candidate_background">#bbffffff</color>
+</resources>
\ No newline at end of file
diff --git a/samples/SoftKeyboard/res/values/dimens.xml b/samples/SoftKeyboard/res/values/dimens.xml
new file mode 100644
index 0000000..cea6e50
--- /dev/null
+++ b/samples/SoftKeyboard/res/values/dimens.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<resources>
+ <dimen name="key_height">50px</dimen>
+ <dimen name="candidate_font_height">16sp</dimen>
+</resources>
\ No newline at end of file
diff --git a/samples/SoftKeyboard/res/values/strings.xml b/samples/SoftKeyboard/res/values/strings.xml
new file mode 100644
index 0000000..c1e306d
--- /dev/null
+++ b/samples/SoftKeyboard/res/values/strings.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Title for Latin keyboard -->
+ <string name="ime_name">Sample Soft Keyboard</string>
+
+ <!-- Symbols that are commonly considered word separators in this language -->
+ <string name="word_separators">\u0020.,;:!?\n()[]*&@{}/<>_+=|"</string>
+
+ <!-- Labels on soft keys -->
+ <string name="label_done">Done</string>
+ <string name="label_search">Search</string>
+ <string name="label_enter">Enter</string>
+ <string name="label_next">Next</string>
+ <string name="label_previous">Previous</string>
+</resources>
diff --git a/samples/SoftKeyboard/res/xml/method.xml b/samples/SoftKeyboard/res/xml/method.xml
new file mode 100644
index 0000000..d246624
--- /dev/null
+++ b/samples/SoftKeyboard/res/xml/method.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * 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.
+ */
+-->
+
+<!-- The attributes in this XML file provide configuration information -->
+<!-- for the Search Manager. -->
+
+<input-method xmlns:android="http://schemas.android.com/apk/res/android" />
diff --git a/samples/SoftKeyboard/res/xml/qwerty.xml b/samples/SoftKeyboard/res/xml/qwerty.xml
new file mode 100755
index 0000000..e81d9f1
--- /dev/null
+++ b/samples/SoftKeyboard/res/xml/qwerty.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
+ android:keyWidth="10%p"
+ android:horizontalGap="0px"
+ android:verticalGap="0px"
+ android:keyHeight="@dimen/key_height"
+ >
+
+ <Row>
+ <Key android:codes="113" android:keyLabel="q" android:keyEdgeFlags="left"/>
+ <Key android:codes="119" android:keyLabel="w"/>
+ <Key android:codes="101" android:keyLabel="e"/>
+ <Key android:codes="114" android:keyLabel="r"/>
+ <Key android:codes="116" android:keyLabel="t"/>
+ <Key android:codes="121" android:keyLabel="y"/>
+ <Key android:codes="117" android:keyLabel="u"/>
+ <Key android:codes="105" android:keyLabel="i"/>
+ <Key android:codes="111" android:keyLabel="o"/>
+ <Key android:codes="112" android:keyLabel="p" android:keyEdgeFlags="right"/>
+ </Row>
+
+ <Row>
+ <Key android:codes="97" android:keyLabel="a" android:horizontalGap="5%p"
+ android:keyEdgeFlags="left"/>
+ <Key android:codes="115" android:keyLabel="s"/>
+ <Key android:codes="100" android:keyLabel="d"/>
+ <Key android:codes="102" android:keyLabel="f"/>
+ <Key android:codes="103" android:keyLabel="g"/>
+ <Key android:codes="104" android:keyLabel="h"/>
+ <Key android:codes="106" android:keyLabel="j"/>
+ <Key android:codes="107" android:keyLabel="k"/>
+ <Key android:codes="108" android:keyLabel="l" android:keyEdgeFlags="right"/>
+ </Row>
+
+ <Row>
+ <Key android:codes="-1" android:keyIcon="@drawable/sym_keyboard_shift"
+ android:keyWidth="15%p" android:isModifier="true"
+ android:isSticky="true" android:keyEdgeFlags="left"/>
+ <Key android:codes="122" android:keyLabel="z"/>
+ <Key android:codes="120" android:keyLabel="x"/>
+ <Key android:codes="99" android:keyLabel="c"/>
+ <Key android:codes="118" android:keyLabel="v"/>
+ <Key android:codes="98" android:keyLabel="b"/>
+ <Key android:codes="110" android:keyLabel="n"/>
+ <Key android:codes="109" android:keyLabel="m"/>
+ <Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
+ android:keyWidth="15%p" android:keyEdgeFlags="right"
+ android:isRepeatable="true"/>
+ </Row>
+
+ <Row android:rowEdgeFlags="bottom">
+ <Key android:codes="-3" android:keyIcon="@drawable/sym_keyboard_done"
+ android:keyWidth="20%p" android:keyEdgeFlags="left"/>
+ <Key android:codes="-2" android:keyLabel="123" android:keyWidth="15%p"/>
+ <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
+ android:keyWidth="30%p" android:isRepeatable="true"/>
+ <Key android:codes="46,44" android:keyLabel=". ,"
+ android:keyWidth="15%p"/>
+ <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
+ android:keyWidth="20%p" android:keyEdgeFlags="right"/>
+ </Row>
+</Keyboard>
+
\ No newline at end of file
diff --git a/samples/SoftKeyboard/res/xml/symbols.xml b/samples/SoftKeyboard/res/xml/symbols.xml
new file mode 100755
index 0000000..a28d752
--- /dev/null
+++ b/samples/SoftKeyboard/res/xml/symbols.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
+ android:keyWidth="10%p"
+ android:horizontalGap="0px"
+ android:verticalGap="0px"
+ android:keyHeight="@dimen/key_height"
+ >
+
+ <Row>
+ <Key android:codes="49" android:keyLabel="1" android:keyEdgeFlags="left"/>
+ <Key android:codes="50" android:keyLabel="2"/>
+ <Key android:codes="51" android:keyLabel="3"/>
+ <Key android:codes="52" android:keyLabel="4"/>
+ <Key android:codes="53" android:keyLabel="5"/>
+ <Key android:codes="54" android:keyLabel="6"/>
+ <Key android:codes="55" android:keyLabel="7"/>
+ <Key android:codes="56" android:keyLabel="8"/>
+ <Key android:codes="57" android:keyLabel="9"/>
+ <Key android:codes="48" android:keyLabel="0" android:keyEdgeFlags="right"/>
+ </Row>
+
+ <Row>
+ <Key android:codes="64" android:keyLabel="\@" android:keyEdgeFlags="left"/>
+ <Key android:codes="35" android:keyLabel="\#"/>
+ <Key android:codes="36" android:keyLabel="$"/>
+ <Key android:codes="37" android:keyLabel="%"/>
+ <Key android:codes="38" android:keyLabel="&"/>
+ <Key android:codes="42" android:keyLabel="*"/>
+ <Key android:codes="45" android:keyLabel="-"/>
+ <Key android:codes="61" android:keyLabel="="/>
+ <Key android:codes="40" android:keyLabel="("/>
+ <Key android:codes="41" android:keyLabel=")" android:keyEdgeFlags="right"/>
+ </Row>
+
+ <Row>
+ <Key android:codes="-1" android:keyIcon="@drawable/sym_keyboard_shift"
+ android:keyWidth="15%p" android:isModifier="true"
+ android:isSticky="true" android:keyEdgeFlags="left"/>
+ <Key android:codes="33" android:keyLabel="!" />
+ <Key android:codes="34" android:keyLabel="""/>
+ <Key android:codes="39" android:keyLabel="\'"/>
+ <Key android:codes="58" android:keyLabel=":"/>
+ <Key android:codes="59" android:keyLabel=";"/>
+ <Key android:codes="47" android:keyLabel="/" />
+ <Key android:codes="63" android:keyLabel="\?"/>
+ <Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
+ android:keyWidth="15%p" android:keyEdgeFlags="right"
+ android:isRepeatable="true"/>
+ </Row>
+
+ <Row android:rowEdgeFlags="bottom">
+ <Key android:codes="-3" android:keyIcon="@drawable/sym_keyboard_done"
+ android:keyWidth="20%p" android:keyEdgeFlags="left" />
+ <Key android:codes="-2" android:keyLabel="ABC" android:keyWidth="15%p" />
+ <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space" android:keyWidth="30%p"
+ android:isRepeatable="true"/>
+ <Key android:codes="44" android:keyLabel="," android:keyWidth="15%p" />
+ <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
+ android:keyWidth="20%p" android:keyEdgeFlags="right"
+ />
+ </Row>
+</Keyboard>
\ No newline at end of file
diff --git a/samples/SoftKeyboard/res/xml/symbols_shift.xml b/samples/SoftKeyboard/res/xml/symbols_shift.xml
new file mode 100755
index 0000000..d7139f3
--- /dev/null
+++ b/samples/SoftKeyboard/res/xml/symbols_shift.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
+ android:keyWidth="10%p"
+ android:horizontalGap="0px"
+ android:verticalGap="0px"
+ android:keyHeight="@dimen/key_height"
+ >
+
+ <Row>
+ <Key android:codes="126" android:keyLabel="~" android:keyEdgeFlags="left"/>
+ <Key android:codes="177" android:keyLabel="±"/>
+ <Key android:codes="215" android:keyLabel="×"/>
+ <Key android:codes="247" android:keyLabel="÷"/>
+ <Key android:codes="8226" android:keyLabel="•"/>
+ <Key android:codes="176" android:keyLabel="°"/>
+ <Key android:codes="96" android:keyLabel="`"/>
+ <Key android:codes="180" android:keyLabel="´"/>
+ <Key android:codes="123" android:keyLabel="{"/>
+ <Key android:codes="125" android:keyLabel="}" android:keyEdgeFlags="right"/>
+ </Row>
+
+ <Row>
+ <Key android:codes="169" android:keyLabel="©" android:keyEdgeFlags="left"/>
+ <Key android:codes="163" android:keyLabel="£"/>
+ <Key android:codes="8364" android:keyLabel="€"/>
+ <Key android:codes="94" android:keyLabel="^"/>
+ <Key android:codes="174" android:keyLabel="®"/>
+ <Key android:codes="165" android:keyLabel="¥"/>
+ <Key android:codes="95" android:keyLabel="_"/>
+ <Key android:codes="43" android:keyLabel="+"/>
+ <Key android:codes="91" android:keyLabel="["/>
+ <Key android:codes="93" android:keyLabel="]" android:keyEdgeFlags="right"/>
+ </Row>
+
+ <Row>
+ <Key android:codes="-1" android:keyIcon="@drawable/sym_keyboard_shift"
+ android:keyWidth="15%p" android:isModifier="true"
+ android:isSticky="true" android:keyEdgeFlags="left"/>
+ <Key android:codes="161" android:keyLabel="¡" />
+ <Key android:codes="60" android:keyLabel="<"/>
+ <Key android:codes="62" android:keyLabel=">"/>
+ <Key android:codes="162" android:keyLabel="¢"/>
+ <Key android:codes="124" android:keyLabel="|"/>
+ <Key android:codes="92" android:keyLabel="\\" />
+ <Key android:codes="191" android:keyLabel="¿"/>
+ <Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
+ android:keyWidth="15%p" android:keyEdgeFlags="right"
+ android:isRepeatable="true"/>
+ </Row>
+
+ <Row android:rowEdgeFlags="bottom">
+ <Key android:codes="-3" android:keyIcon="@drawable/sym_keyboard_done"
+ android:keyWidth="20%p" android:keyEdgeFlags="left" />
+ <Key android:codes="-2" android:keyLabel="ABC" android:keyWidth="15%p" />
+ <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space" android:keyWidth="30%p"
+ android:isRepeatable="true"/>
+ <Key android:codes="8230" android:keyLabel="…" android:keyWidth="15%p" />
+ <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
+ android:keyWidth="20%p" android:keyEdgeFlags="right" />
+ </Row>
+</Keyboard>
diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/CandidateView.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/CandidateView.java
new file mode 100755
index 0000000..1e79cd7
--- /dev/null
+++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/CandidateView.java
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2008-2009 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.example.android.softkeyboard;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.View;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CandidateView extends View {
+
+ private static final int OUT_OF_BOUNDS = -1;
+
+ private SoftKeyboard mService;
+ private List<String> mSuggestions;
+ private int mSelectedIndex;
+ private int mTouchX = OUT_OF_BOUNDS;
+ private Drawable mSelectionHighlight;
+ private boolean mTypedWordValid;
+
+ private Rect mBgPadding;
+
+ private static final int MAX_SUGGESTIONS = 32;
+ private static final int SCROLL_PIXELS = 20;
+
+ private int[] mWordWidth = new int[MAX_SUGGESTIONS];
+ private int[] mWordX = new int[MAX_SUGGESTIONS];
+
+ private static final int X_GAP = 10;
+
+ private static final List<String> EMPTY_LIST = new ArrayList<String>();
+
+ private int mColorNormal;
+ private int mColorRecommended;
+ private int mColorOther;
+ private Paint mPaint;
+ private boolean mScrolled;
+ private int mTargetScrollX;
+
+ private int mTotalWidth;
+
+ private GestureDetector mGestureDetector;
+
+ /**
+ * Construct a CandidateView for showing suggested words for completion.
+ * @param context
+ * @param attrs
+ */
+ public CandidateView(Context context) {
+ super(context);
+ mSelectionHighlight = context.getResources().getDrawable(
+ android.R.drawable.list_selector_background);
+ mSelectionHighlight.setState(new int[] {
+ android.R.attr.state_enabled,
+ android.R.attr.state_focused,
+ android.R.attr.state_window_focused,
+ android.R.attr.state_pressed
+ });
+
+ Resources r = context.getResources();
+
+ setBackgroundColor(r.getColor(R.color.candidate_background));
+
+ mColorNormal = r.getColor(R.color.candidate_normal);
+ mColorRecommended = r.getColor(R.color.candidate_recommended);
+ mColorOther = r.getColor(R.color.candidate_other);
+
+ mPaint = new Paint();
+ mPaint.setColor(mColorNormal);
+ mPaint.setAntiAlias(true);
+ mPaint.setTextSize(r.getDimensionPixelSize(R.dimen.candidate_font_height));
+ mPaint.setStrokeWidth(0);
+
+ mGestureDetector = new GestureDetector(new GestureDetector.SimpleOnGestureListener() {
+ @Override
+ public boolean onScroll(MotionEvent e1, MotionEvent e2,
+ float distanceX, float distanceY) {
+ mScrolled = true;
+ int sx = getScrollX();
+ sx += distanceX;
+ if (sx < 0) {
+ sx = 0;
+ }
+ if (sx + getWidth() > mTotalWidth) {
+ sx -= distanceX;
+ }
+ mTargetScrollX = sx;
+ scrollTo(sx, getScrollY());
+ invalidate();
+ return true;
+ }
+ });
+ setHorizontalFadingEdgeEnabled(true);
+ setWillNotDraw(false);
+ setHorizontalScrollBarEnabled(false);
+ setVerticalScrollBarEnabled(false);
+ }
+
+ /**
+ * A connection back to the service to communicate with the text field
+ * @param listener
+ */
+ public void setService(SoftKeyboard listener) {
+ mService = listener;
+ }
+
+ @Override
+ public int computeHorizontalScrollRange() {
+ return mTotalWidth;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int measuredWidth = resolveSize(50, widthMeasureSpec);
+
+ // Get the desired height of the icon menu view (last row of items does
+ // not have a divider below)
+ Rect padding = new Rect();
+ mSelectionHighlight.getPadding(padding);
+ final int desiredHeight = ((int)mPaint.getTextSize()) + 1
+ + padding.top + padding.bottom;
+
+ // Maximum possible width and desired height
+ setMeasuredDimension(measuredWidth,
+ resolveSize(desiredHeight, heightMeasureSpec));
+ }
+
+ /**
+ * If the canvas is null, then only touch calculations are performed to pick the target
+ * candidate.
+ */
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (canvas != null) {
+ super.onDraw(canvas);
+ }
+ mTotalWidth = 0;
+ if (mSuggestions == null) return;
+
+ if (mBgPadding == null) {
+ mBgPadding = new Rect(0, 0, 0, 0);
+ if (getBackground() != null) {
+ getBackground().getPadding(mBgPadding);
+ }
+ }
+ int x = 0;
+ final int count = mSuggestions.size();
+ final int height = getHeight();
+ final Rect bgPadding = mBgPadding;
+ final Paint paint = mPaint;
+ final int touchX = mTouchX;
+ final int scrollX = getScrollX();
+ final boolean scrolled = mScrolled;
+ final boolean typedWordValid = mTypedWordValid;
+ final int y = (int) (height + mPaint.getTextSize()) / 2;
+
+ for (int i = 0; i < count; i++) {
+ String suggestion = mSuggestions.get(i);
+ float textWidth = paint.measureText(suggestion);
+ final int wordWidth = (int) textWidth + X_GAP * 2;
+
+ mWordX[i] = x;
+ mWordWidth[i] = wordWidth;
+ paint.setColor(mColorNormal);
+ if (touchX + scrollX >= x && touchX + scrollX < x + wordWidth && !scrolled) {
+ if (canvas != null) {
+ canvas.translate(x, 0);
+ mSelectionHighlight.setBounds(0, bgPadding.top, wordWidth, height);
+ mSelectionHighlight.draw(canvas);
+ canvas.translate(-x, 0);
+ }
+ mSelectedIndex = i;
+ }
+
+ if (canvas != null) {
+ if ((i == 1 && !typedWordValid) || (i == 0 && typedWordValid)) {
+ paint.setFakeBoldText(true);
+ paint.setColor(mColorRecommended);
+ } else if (i != 0) {
+ paint.setColor(mColorOther);
+ }
+ canvas.drawText(suggestion, x + X_GAP, y, paint);
+ paint.setColor(mColorOther);
+ canvas.drawLine(x + wordWidth + 0.5f, bgPadding.top,
+ x + wordWidth + 0.5f, height + 1, paint);
+ paint.setFakeBoldText(false);
+ }
+ x += wordWidth;
+ }
+ mTotalWidth = x;
+ if (mTargetScrollX != getScrollX()) {
+ scrollToTarget();
+ }
+ }
+
+ private void scrollToTarget() {
+ int sx = getScrollX();
+ if (mTargetScrollX > sx) {
+ sx += SCROLL_PIXELS;
+ if (sx >= mTargetScrollX) {
+ sx = mTargetScrollX;
+ requestLayout();
+ }
+ } else {
+ sx -= SCROLL_PIXELS;
+ if (sx <= mTargetScrollX) {
+ sx = mTargetScrollX;
+ requestLayout();
+ }
+ }
+ scrollTo(sx, getScrollY());
+ invalidate();
+ }
+
+ public void setSuggestions(List<String> suggestions, boolean completions,
+ boolean typedWordValid) {
+ clear();
+ if (suggestions != null) {
+ mSuggestions = new ArrayList<String>(suggestions);
+ }
+ mTypedWordValid = typedWordValid;
+ scrollTo(0, 0);
+ mTargetScrollX = 0;
+ // Compute the total width
+ onDraw(null);
+ invalidate();
+ requestLayout();
+ }
+
+ public void clear() {
+ mSuggestions = EMPTY_LIST;
+ mTouchX = OUT_OF_BOUNDS;
+ mSelectedIndex = -1;
+ invalidate();
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent me) {
+
+ if (mGestureDetector.onTouchEvent(me)) {
+ return true;
+ }
+
+ int action = me.getAction();
+ int x = (int) me.getX();
+ int y = (int) me.getY();
+ mTouchX = x;
+
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ mScrolled = false;
+ invalidate();
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (y <= 0) {
+ // Fling up!?
+ if (mSelectedIndex >= 0) {
+ mService.pickSuggestionManually(mSelectedIndex);
+ mSelectedIndex = -1;
+ }
+ }
+ invalidate();
+ break;
+ case MotionEvent.ACTION_UP:
+ if (!mScrolled) {
+ if (mSelectedIndex >= 0) {
+ mService.pickSuggestionManually(mSelectedIndex);
+ }
+ }
+ mSelectedIndex = -1;
+ removeHighlight();
+ requestLayout();
+ break;
+ }
+ return true;
+ }
+
+ /**
+ * For flick through from keyboard, call this method with the x coordinate of the flick
+ * gesture.
+ * @param x
+ */
+ public void takeSuggestionAt(float x) {
+ mTouchX = (int) x;
+ // To detect candidate
+ onDraw(null);
+ if (mSelectedIndex >= 0) {
+ mService.pickSuggestionManually(mSelectedIndex);
+ }
+ invalidate();
+ }
+
+ private void removeHighlight() {
+ mTouchX = OUT_OF_BOUNDS;
+ invalidate();
+ }
+}
diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboard.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboard.java
new file mode 100644
index 0000000..944cefb
--- /dev/null
+++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboard.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2008-2009 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.example.android.softkeyboard;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.inputmethodservice.Keyboard;
+
+public class LatinKeyboard extends Keyboard {
+
+ public LatinKeyboard(Context context, int xmlLayoutResId) {
+ super(context, xmlLayoutResId);
+ }
+
+ public LatinKeyboard(Context context, int layoutTemplateResId,
+ CharSequence characters, int columns, int horizontalPadding) {
+ super(context, layoutTemplateResId, characters, columns, horizontalPadding);
+ }
+
+ @Override
+ protected Key createKeyFromXml(Resources res, Row parent, int x, int y,
+ XmlResourceParser parser) {
+ return new LatinKey(res, parent, x, y, parser);
+ }
+
+ static class LatinKey extends Keyboard.Key {
+
+ public LatinKey(Resources res, Keyboard.Row parent, int x, int y, XmlResourceParser parser) {
+ super(res, parent, x, y, parser);
+ }
+
+ /**
+ * Overriding this method so that we can reduce the target area for the key that
+ * closes the keyboard.
+ */
+ @Override
+ public boolean isInside(int x, int y) {
+ return super.isInside(x, codes[0] == KEYCODE_CANCEL ? y - 10 : y);
+ }
+ }
+
+}
diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboardView.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboardView.java
new file mode 100644
index 0000000..7464607
--- /dev/null
+++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboardView.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008-2009 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.example.android.softkeyboard;
+
+import android.content.Context;
+import android.inputmethodservice.Keyboard;
+import android.inputmethodservice.KeyboardView;
+import android.inputmethodservice.Keyboard.Key;
+import android.util.AttributeSet;
+
+public class LatinKeyboardView extends KeyboardView {
+
+ static final int KEYCODE_OPTIONS = -100;
+
+ public LatinKeyboardView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public LatinKeyboardView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ protected boolean onLongPress(Key key) {
+ if (key.codes[0] == Keyboard.KEYCODE_CANCEL) {
+ getOnKeyboardActionListener().onKey(KEYCODE_OPTIONS, null);
+ return true;
+ } else {
+ return super.onLongPress(key);
+ }
+ }
+}
diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java
new file mode 100644
index 0000000..baa4594
--- /dev/null
+++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java
@@ -0,0 +1,461 @@
+/*
+ * Copyright (C) 2008-2009 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.example.android.softkeyboard;
+
+import android.content.Context;
+import android.inputmethodservice.InputMethodService;
+import android.inputmethodservice.Keyboard;
+import android.inputmethodservice.KeyboardView;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Example of writing an input method for a soft keyboard. This code is
+ * focused on simplicity over completeness, so it should in no way be considered
+ * to be a complete soft keyboard implementation. Its purpose is to provide
+ * a basic example for how you would get started writing an input method, to
+ * be fleshed out as appropriate.
+ */
+public class SoftKeyboard extends InputMethodService
+ implements KeyboardView.OnKeyboardActionListener {
+ static final boolean DEBUG = false;
+
+ private KeyboardView mInputView;
+ private CandidateView mCandidateView;
+ private CompletionInfo[] mCompletions;
+
+ private StringBuilder mComposing = new StringBuilder();
+ private boolean mPredicting;
+ private boolean mPredictionOn;
+ private boolean mCompletionOn;
+ private int mLastDisplayWidth;
+ private boolean mCapsLock;
+ private long mLastShiftTime;
+
+ private Keyboard mSymbolsKeyboard;
+ private Keyboard mSymbolsShiftedKeyboard;
+ private Keyboard mQwertyKeyboard;
+
+ private String mWordSeparators;
+
+ private InputConnection mOldConnection;
+
+ private void makeKeyboards() {
+ // Configuration change is coming after the keyboard gets recreated. So don't rely on that.
+ // If keyboards have already been made, check if we have a screen width change and
+ // create the keyboard layouts again at the correct orientation
+ if (mQwertyKeyboard != null) {
+ WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
+ int displayWidth = wm.getDefaultDisplay().getWidth();
+ if (displayWidth == mLastDisplayWidth) return;
+ mLastDisplayWidth = displayWidth;
+ }
+ mQwertyKeyboard = new LatinKeyboard(this, R.xml.qwerty);
+ mSymbolsKeyboard = new LatinKeyboard(this, R.xml.symbols);
+ mSymbolsShiftedKeyboard = new LatinKeyboard(this, R.xml.symbols_shift);
+ }
+
+ @Override public void onCreate() {
+ super.onCreate();
+ //setStatusIcon(R.drawable.ime_qwerty);
+ makeKeyboards();
+ mWordSeparators = getResources().getString(R.string.word_separators);
+ }
+
+ @Override
+ public View onCreateInputView() {
+ makeKeyboards();
+ mInputView = (KeyboardView) getLayoutInflater().inflate(
+ R.layout.input, null);
+ mInputView.setOnKeyboardActionListener(this);
+ mInputView.setKeyboard(mQwertyKeyboard);
+ return mInputView;
+ }
+
+ @Override
+ public View onCreateCandidatesView() {
+ makeKeyboards();
+ mCandidateView = new CandidateView(this);
+ mCandidateView.setService(this);
+ return mCandidateView;
+ }
+
+ @Override
+ public void onStartInputView(EditorInfo attribute, boolean restarting) {
+ // In landscape mode, this method gets called without the input view being created.
+ if (mInputView == null) {
+ return;
+ }
+
+ if (mQwertyKeyboard == null) {
+ makeKeyboards();
+ }
+
+ if (mOldConnection != null) {
+ commitTyped(mOldConnection);
+ }
+
+ mPredictionOn = false;
+ mCompletionOn = false;
+ mCompletions = null;
+ switch (attribute.inputType&EditorInfo.TYPE_MASK_CLASS) {
+ case EditorInfo.TYPE_CLASS_NUMBER:
+ case EditorInfo.TYPE_CLASS_DATETIME:
+ mInputView.setKeyboard(mSymbolsKeyboard);
+ break;
+ case EditorInfo.TYPE_CLASS_PHONE:
+ mInputView.setKeyboard(mSymbolsKeyboard);
+ break;
+ default:
+ mInputView.setKeyboard(mQwertyKeyboard);
+ //startPrediction();
+ mPredictionOn = true;
+ // Make sure that passwords are not displayed in candidate view
+ int variation = attribute.inputType & EditorInfo.TYPE_MASK_VARIATION;
+ if (variation == EditorInfo.TYPE_TEXT_VARIATION_PASSWORD) {
+ mPredictionOn = false;
+ }
+ if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
+ || variation == EditorInfo.TYPE_TEXT_VARIATION_URI) {
+ mPredictionOn = false;
+ }
+ if ((attribute.inputType&EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) {
+ mPredictionOn = false;
+ mCompletionOn = isFullscreenMode();
+ }
+ updateShiftKeyState(attribute);
+ break;
+ }
+ mInputView.closing();
+ mComposing.setLength(0);
+ mCandidateView.setSuggestions(null, false, false);
+ mOldConnection = getCurrentInputConnection();
+ setCandidatesViewShown(mPredictionOn || mCompletionOn);
+ }
+
+ @Override
+ public void onFinishInput() {
+ super.onFinishInput();
+ commitTyped(mOldConnection);
+ if (mInputView != null) {
+ mInputView.closing();
+ }
+ }
+
+ @Override
+ public void onDisplayCompletions(CompletionInfo[] completions) {
+ if (false) {
+ Log.i("foo", "Received completions:");
+ for (int i=0; i<(completions != null ? completions.length : 0); i++) {
+ Log.i("foo", " #" + i + ": " + completions[i]);
+ }
+ }
+ if (mCompletionOn) {
+ mCompletions = completions;
+ if (completions == null) {
+ mCandidateView.setSuggestions(null, false, false);
+ return;
+ }
+
+ List<String> stringList = new ArrayList<String>();
+ for (int i=0; i<(completions != null ? completions.length : 0); i++) {
+ CompletionInfo ci = completions[i];
+ if (ci != null) stringList.add(ci.getText().toString());
+ }
+ mCandidateView.setSuggestions(stringList, true, true);
+ }
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_BACK:
+ if (event.getRepeatCount() == 0 && mInputView != null) {
+ if (mInputView.handleBack()) {
+ return true;
+ }
+ }
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ case KeyEvent.KEYCODE_DPAD_UP:
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ abortComposition();
+ break;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ case KeyEvent.KEYCODE_DPAD_UP:
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ // Enable shift key and DPAD to do selections
+ if (mInputView != null && mInputView.isShown() && mInputView.isShifted()) {
+ event = new KeyEvent(event.getDownTime(), event.getEventTime(),
+ event.getAction(), event.getKeyCode(), event.getRepeatCount(),
+ KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON);
+ getCurrentInputConnection().sendKeyEvent(event);
+ return true;
+ }
+ break;
+ }
+ return super.onKeyUp(keyCode, event);
+ }
+
+ private void commitTyped(InputConnection inputConnection) {
+ if (mComposing.length() > 0) {
+ inputConnection.commitText(mComposing, mComposing.length());
+ mComposing.setLength(0);
+ updateCandidates();
+ }
+ }
+
+ public void updateShiftKeyState(EditorInfo attr) {
+ if (attr != null
+ && mInputView != null && mQwertyKeyboard == mInputView.getKeyboard()) {
+ int caps = getCurrentInputConnection().getCursorCapsMode(attr.inputType);
+ mInputView.setShifted(mCapsLock || caps != 0);
+ }
+ }
+
+ private boolean isAlphabet(int code) {
+ if (Character.isLetter(code)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private void keyDownUp(int keyEventCode) {
+ getCurrentInputConnection().sendKeyEvent(
+ new KeyEvent(KeyEvent.ACTION_DOWN, keyEventCode));
+ getCurrentInputConnection().sendKeyEvent(
+ new KeyEvent(KeyEvent.ACTION_UP, keyEventCode));
+ }
+
+ private void sendKey(int keyCode) {
+ switch (keyCode) {
+ case 10:
+ keyDownUp(KeyEvent.KEYCODE_ENTER);
+ break;
+ default:
+ if (keyCode >= '0' && keyCode <= '9') {
+ keyDownUp(keyCode - '0' + KeyEvent.KEYCODE_0);
+ } else {
+ getCurrentInputConnection().commitText(String.valueOf((char) keyCode), 1);
+ }
+ break;
+ }
+ }
+
+ // Implementation of KeyboardViewListener
+
+ public void onKey(int primaryCode, int[] keyCodes) {
+ if (isWordSeparator(primaryCode)) {
+ // Handle separator
+ if (mPredicting) {
+ commitTyped(getCurrentInputConnection());
+ }
+ sendKey(primaryCode);
+ updateShiftKeyState(getCurrentInputInfo());
+ } else if (primaryCode == Keyboard.KEYCODE_DELETE) {
+ handleBackspace();
+ } else if (primaryCode == Keyboard.KEYCODE_SHIFT) {
+ handleShift();
+ } else if (primaryCode == Keyboard.KEYCODE_CANCEL) {
+ handleClose();
+ return;
+ } else if (primaryCode == LatinKeyboardView.KEYCODE_OPTIONS) {
+ // Show a menu or somethin'
+ } else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {
+ Keyboard current = mInputView.getKeyboard();
+ if (current == mSymbolsKeyboard || current == mSymbolsShiftedKeyboard) {
+ current = mQwertyKeyboard;
+ } else {
+ current = mSymbolsKeyboard;
+ }
+ mInputView.setKeyboard(current);
+ if (current == mSymbolsKeyboard) {
+ current.setShifted(false);
+ }
+ } else {
+ handleCharacter(primaryCode, keyCodes);
+ }
+ }
+
+ /**
+ * Update the list of available candidates from the current composing
+ * text. This will need to be filled in by however you are determining
+ * candidates.
+ */
+ private void updateCandidates() {
+ if (!mCompletionOn) {
+ if (mComposing.length() > 0) {
+ ArrayList<String> list = new ArrayList<String>();
+ list.add(mComposing.toString());
+ mCandidateView.setSuggestions(list, true, true);
+ } else {
+ mCandidateView.setSuggestions(null, false, false);
+ }
+ }
+ }
+
+ private void handleBackspace() {
+ if (mPredicting) {
+ final int length = mComposing.length();
+ if (length > 0) {
+ mComposing.delete(length - 1, length);
+ getCurrentInputConnection().setComposingText(mComposing, mComposing.length());
+ updateCandidates();
+ if (mComposing.length() == 0) {
+ mPredicting = false;
+ }
+ } else {
+ getCurrentInputConnection().deleteSurroundingText(1, 0);
+ }
+ } else {
+ //getCurrentInputConnection().deleteSurroundingText(1, 0);
+ keyDownUp(KeyEvent.KEYCODE_DEL);
+ }
+ updateShiftKeyState(getCurrentInputInfo());
+ }
+
+ private void handleShift() {
+ Keyboard currentKeyboard = mInputView.getKeyboard();
+ if (mQwertyKeyboard == currentKeyboard) {
+ // Alphabet keyboard
+ checkToggleCapsLock();
+ mInputView.setShifted(mCapsLock || !mInputView.isShifted());
+ } else if (currentKeyboard == mSymbolsKeyboard) {
+ mSymbolsKeyboard.setShifted(true);
+ mInputView.setKeyboard(mSymbolsShiftedKeyboard);
+ mSymbolsShiftedKeyboard.setShifted(true);
+ } else if (currentKeyboard == mSymbolsShiftedKeyboard) {
+ mSymbolsShiftedKeyboard.setShifted(false);
+ mInputView.setKeyboard(mSymbolsKeyboard);
+ mSymbolsKeyboard.setShifted(false);
+ }
+ }
+
+ private void handleCharacter(int primaryCode, int[] keyCodes) {
+ if (isAlphabet(primaryCode) && mPredictionOn && !isCursorTouchingWord()) {
+ if (!mPredicting) {
+ mPredicting = true;
+ mComposing.setLength(0);
+ }
+ }
+ if (mInputView.isShifted()) {
+ primaryCode = Character.toUpperCase(primaryCode);
+ }
+ mComposing.append((char) primaryCode);
+ getCurrentInputConnection().setComposingText(mComposing, mComposing.length());
+ updateShiftKeyState(getCurrentInputInfo());
+ updateCandidates();
+ }
+
+ private void handleClose() {
+ commitTyped(getCurrentInputConnection());
+ dismissSoftInput();
+ mInputView.closing();
+ }
+
+ private void checkToggleCapsLock() {
+ long now = System.currentTimeMillis();
+ if (mLastShiftTime + 800 > now) {
+ mCapsLock = !mCapsLock;
+ mLastShiftTime = 0;
+ } else {
+ mLastShiftTime = now;
+ }
+ }
+
+ private boolean isCursorTouchingWord() {
+ CharSequence toLeft = getCurrentInputConnection().getTextBeforeCursor(1);
+ CharSequence toRight = getCurrentInputConnection().getTextAfterCursor(1);
+ if (!TextUtils.isEmpty(toLeft)
+ && !isWordSeparator(toLeft.charAt(0))) {
+ return true;
+ }
+ if (!TextUtils.isEmpty(toRight)
+ && !isWordSeparator(toRight.charAt(0))) {
+ return true;
+ }
+ return false;
+ }
+
+ protected String getWordSeparators() {
+ return mWordSeparators;
+ }
+
+ public boolean isWordSeparator(int code) {
+ String separators = getWordSeparators();
+ return separators.contains(String.valueOf((char)code));
+ }
+
+ public void pickDefaultCandidate() {
+ pickSuggestionManually(0);
+ }
+
+ public void pickSuggestionManually(int index) {
+ if (mCompletionOn && mCompletions != null && index >= 0
+ && index < mCompletions.length) {
+ CompletionInfo ci = mCompletions[index];
+ getCurrentInputConnection().commitCompletion(ci);
+ if (mCandidateView != null) {
+ mCandidateView.clear();
+ }
+ updateShiftKeyState(getCurrentInputInfo());
+ }
+ }
+
+ public void swipeRight() {
+ if (mCompletionOn) {
+ pickDefaultCandidate();
+ }
+ }
+
+ public void swipeLeft() {
+ handleBackspace();
+ }
+
+ public void swipeDown() {
+ handleClose();
+ }
+
+ public void swipeUp() {
+ // ?
+ }
+
+ private void abortComposition() {
+ commitTyped(getCurrentInputConnection());
+ mComposing.setLength(0); // Don't want to allow uncommit after this
+ updateCandidates();
+ }
+}
diff --git a/simulator/app/Android.mk b/simulator/app/Android.mk
index 59c147c..c6e1d14 100644
--- a/simulator/app/Android.mk
+++ b/simulator/app/Android.mk
@@ -1,7 +1,7 @@
# Copyright 2005 The Android Open Source Project
#
-ifneq ($(TARGET_ARCH),arm)
+ifeq ($(TARGET_SIMULATOR),true)
LOCAL_PATH := $(call my-dir)
@@ -127,4 +127,4 @@
ALL_DEFAULT_INSTALLED_MODULES += $(asset_target)
-endif
+endif # $(TARGET_SIMULATOR) == true
diff --git a/simulator/app/DeviceManager.cpp b/simulator/app/DeviceManager.cpp
index 1f65d99..a859c63 100644
--- a/simulator/app/DeviceManager.cpp
+++ b/simulator/app/DeviceManager.cpp
@@ -61,7 +61,7 @@
printf("Sim: Waiting for old runtime thread..."); fflush(stdout);
code = mThread->Wait(); // join the old thread
- printf("done (code=%d)\n", (int) code);
+ printf("done (code=%ld)\n", (long) code);
}
delete mThread;
mThread = NULL;
@@ -187,7 +187,7 @@
// clean up old thread
printf("Sim: Waiting for old runtime thread..."); fflush(stdout);
code = mThread->Wait(); // join the old thread
- printf("done (code=%d)\n", (int) code);
+ printf("done (code=%ld)\n", (long) code);
delete mThread;
mThread = NULL;
@@ -916,13 +916,13 @@
* Right now we're just shipping a big binary blob over.
*/
assert(android::Simulator::kValuesPerDisplay >= 5);
- long buf[1 + 1 + mpDeviceManager->GetNumDisplays() *
+ int buf[1 + 1 + mpDeviceManager->GetNumDisplays() *
android::Simulator::kValuesPerDisplay];
buf[0] = android::Simulator::kDisplayConfigMagic;
buf[1] = mpDeviceManager->GetNumDisplays();
for (int i = 0; i < mpDeviceManager->GetNumDisplays(); i++) {
DeviceManager::Display* pDisplay = mpDeviceManager->GetDisplay(i);
- long* pBuf = &buf[2 + android::Simulator::kValuesPerDisplay * i];
+ int* pBuf = &buf[2 + android::Simulator::kValuesPerDisplay * i];
pBuf[0] = pDisplay->GetWidth();
pBuf[1] = pDisplay->GetHeight();
diff --git a/simulator/app/DeviceWindow.cpp b/simulator/app/DeviceWindow.cpp
index 619a614..a15b03b 100644
--- a/simulator/app/DeviceWindow.cpp
+++ b/simulator/app/DeviceWindow.cpp
@@ -140,9 +140,9 @@
void DeviceWindow::OnUserEvent(UserEvent& event)
{
wxBitmap* pBitmap;
- int displayIndex;
+ long displayIndex;
- displayIndex = (int) event.GetData();
+ displayIndex = (long) event.GetData();
//printf("GOT UAE %d\n", displayIndex);
diff --git a/simulator/app/LogWindow.cpp b/simulator/app/LogWindow.cpp
index 53ba9d0..b19debb 100644
--- a/simulator/app/LogWindow.cpp
+++ b/simulator/app/LogWindow.cpp
@@ -423,7 +423,7 @@
selection = event.GetInt();
wxComboBox* pCombo = (wxComboBox*) FindWindow(IDC_LOG_LEVEL);
- priority = (android_LogPriority) (int)pCombo->GetClientData(event.GetInt());
+ priority = (android_LogPriority) (long)pCombo->GetClientData(event.GetInt());
printf("Sim: log level selected: %d (%s)\n", (int) priority,
(const char*) gLogLevels[selection].name.ToAscii());
diff --git a/simulator/app/PropertyServer.cpp b/simulator/app/PropertyServer.cpp
index ee17657..565cc09 100644
--- a/simulator/app/PropertyServer.cpp
+++ b/simulator/app/PropertyServer.cpp
@@ -129,10 +129,12 @@
{ "app.setupwizard.disable", "1" },
/* Dalvik options, set by AndroidRuntime */
- { "dalvik.vm.execution-mode", "int:portable" },
+ { "dalvik.vm.stack-trace-file", "/data/anr/traces.txt" },
+ //{ "dalvik.vm.execution-mode", "int:portable" },
{ "dalvik.vm.enableassertions", "all" }, // -ea
{ "dalvik.vm.verify-bytecode", "false" }, // -Xverify
{ "dalvik.vm.deadlock-predict", "off" }, // -Xdeadlockpredict
+ //{ "dalvik.vm.jniopts", "forcecopy" }, // -Xjniopts
{ "log.redirect-stdio", "false" }, // -Xlog-stdio
/* SurfaceFlinger options */
diff --git a/simulator/wrapsim/Android.mk b/simulator/wrapsim/Android.mk
index 7ac8359..ca9a592 100644
--- a/simulator/wrapsim/Android.mk
+++ b/simulator/wrapsim/Android.mk
@@ -4,6 +4,7 @@
# Build instructions for simulator LD_PRELOAD wrapper.
#
ifneq ($(TARGET_ARCH),arm)
+ifeq ($(TARGET_SIMULATOR),true)
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -29,10 +30,13 @@
# Relying on other Android libraries is probably a bad idea, since any
# library or system calls they make could lead to recursive behavior.
-#
-#LOCAL_SHARED_LIBRARIES +=
+LOCAL_LDLIBS += -lpthread -ldl
-LOCAL_LDLIBS += -lpthread -ldl -lesd
+ifeq ($(BUILD_SIM_WITHOUT_AUDIO),true)
+LOCAL_CFLAGS += -DBUILD_SIM_WITHOUT_AUDIO=1
+else
+LOCAL_LDLIBS += -lesd
+endif
include $(BUILD_SHARED_LIBRARY)
@@ -49,5 +53,6 @@
LOCAL_MODULE := launch-wrapper
include $(BUILD_EXECUTABLE)
+endif # ifeq ($(TARGET_SIMULATOR),true)
endif
# ifneq ($(TARGET_ARCH),arm)
diff --git a/simulator/wrapsim/DevAudio.c b/simulator/wrapsim/DevAudio.c
index 0f52b81..752ee65 100644
--- a/simulator/wrapsim/DevAudio.c
+++ b/simulator/wrapsim/DevAudio.c
@@ -30,6 +30,9 @@
*/
static int configureInitialState(const char* pathName, AudioState* audioState)
{
+#if BUILD_SIM_WITHOUT_AUDIO
+ return 0;
+#else
esd_player_info_t *pi;
audioState->fd = -1;
audioState->sourceId = -1;
@@ -62,6 +65,7 @@
}
printf("Couldn't open audio device. Faking it.\n");
return 0;
+#endif
}
/*
@@ -71,6 +75,9 @@
*/
static ssize_t writeAudio(FakeDev* dev, int fd, const void* buf, size_t count)
{
+#if BUILD_SIM_WITHOUT_AUDIO
+ return 0;
+#else
AudioState *state = (AudioState*)dev->state;
if (state->fd >= 0)
return _ws_write(state->fd, buf, count);
@@ -78,6 +85,7 @@
// fake timing
usleep(count * 10000 / 441 * 4);
return count;
+#endif
}
/*
@@ -93,11 +101,15 @@
*/
static int closeAudio(FakeDev* dev, int fd)
{
+#if BUILD_SIM_WITHOUT_AUDIO
+ return 0;
+#else
AudioState *state = (AudioState*)dev->state;
close(state->fd);
free(state);
dev->state = NULL;
return 0;
+#endif
}
/*
diff --git a/simulator/wrapsim/DevFb.c b/simulator/wrapsim/DevFb.c
index 42a9d9a..c54403e 100644
--- a/simulator/wrapsim/DevFb.c
+++ b/simulator/wrapsim/DevFb.c
@@ -63,7 +63,7 @@
fbState->vinfo.blue.length = 5;
fbState->vinfo.width = 51; // physical dimension, used for dpi
- fbState->vinfo.height = 38;
+ fbState->vinfo.height = 76;
fbState->vinfo.pixclock = 103092;
fbState->vinfo.upper_margin = 3;
diff --git a/tools/activitycreator/src/com/android/activitycreator/ActivityCreator.java b/tools/activitycreator/src/com/android/activitycreator/ActivityCreator.java
index c71ca6e..f7db7df 100644
--- a/tools/activitycreator/src/com/android/activitycreator/ActivityCreator.java
+++ b/tools/activitycreator/src/com/android/activitycreator/ActivityCreator.java
@@ -44,6 +44,9 @@
* @hide
*/
public class ActivityCreator {
+ // FIXME: target platform must be provided by the user
+ private final String mTargetPlatform = "android-1.1";
+
/** Whether we are in silent mode (i.e.: don't print any non-error messages) */
private boolean mSilent;
@@ -53,7 +56,10 @@
/** Path to SDK */
private String mSdkDir;
- /** Path to lib */
+ /** Path to target platform's template folder */
+ private String mTemplateDir;
+
+ /** Path to tools/lib for the build templates */
private String mLibDir;
/** Path to output */
@@ -115,6 +121,8 @@
mSdkDir = toolsDir.getParent();
mLibDir = mToolsDir + File.separator + "lib";
+ mTemplateDir = mSdkDir + File.separator + "platforms" + File.separator +
+ mTargetPlatform + File.separator + "templates";
try {
mOutDir = new File("").getCanonicalPath();
} catch (IOException e) {
@@ -129,6 +137,10 @@
printHelpAndExit("ERROR: SDK directory does not exist.");
}
+ if (!(new File(mTemplateDir).exists())) {
+ printHelpAndExit("ERROR: Target platform templates directory does not exist.");
+ }
+
if (!(new File(mLibDir).exists())) {
printHelpAndExit("ERROR: Library directory does not exist.");
}
@@ -263,20 +275,95 @@
}
/**
+ * Installs a destination file that is based on a code template file at the source.
+ * For each match of each key in keywords will be replaced with its
+ * corresponding value in the destination file.
+ *
+ * Invokes {@link #installProjectTemplate(String, String, Map, boolean, String)} with
+ * the main project output directory (#mOutDir) as the last argument.
+ *
+ * @param source the name of to the source template file
+ * @param dest the path to the destination file
+ * @param keywords in the destination file, the keys will be replaced by their values
+ * @param force True to force writing the file even if it already exists
+ *
+ * @see #installProjectTemplate(String, String, Map, boolean, String)
+ */
+ private void installProjectTemplate(String source, String dest,
+ Map<String, String> keywords, boolean force) {
+ installProjectTemplate(source, dest, keywords, force, mOutDir);
+ }
+
+ /**
+ * Installs a destination file that is based on a code template file at the source.
+ * For each match of each key in keywords will be replaced with its
+ * corresponding value in the destination file.
+ *
+ * @param source the name of to the source template file
+ * @param dest the path to the destination file
+ * @param keywords in the destination file, the keys will be replaced by their values
+ * @param force True to force writing the file even if it already exists
+ * @param outDir the output directory to copy the template file to
+ */
+ private void installProjectTemplate(String source, String dest,
+ Map<String, String> keywords, boolean force, String outDir) {
+ final String sourcePath = mTemplateDir + File.separator + source;
+ final String destPath = outDir + File.separator + dest;
+
+ installFullPathTemplate(sourcePath, destPath, keywords, force);
+ }
+
+ /**
+ * Installs a destination file that is based on a build template file at the source.
+ * For each match of each key in keywords will be replaced with its
+ * corresponding value in the destination file.
+ *
+ * Invokes {@link #installBuildTemplate(String, String, Map, boolean, String)} with
+ * the main project output directory (#mOutDir) as the last argument.
+ *
+ * @param source the name of to the source template file
+ * @param dest the path to the destination file
+ * @param keywords in the destination file, the keys will be replaced by their values
+ * @param force True to force writing the file even if it already exists
+ *
+ * @see #installBuildTemplate(String, String, Map, boolean, String)
+ */
+ private void installBuildTemplate(String source, String dest,
+ Map<String, String> keywords, boolean force) {
+ installBuildTemplate(source, dest, keywords, force, mOutDir);
+ }
+
+ /**
+ * Installs a destination file that is based on a build template file at the source.
+ * For each match of each key in keywords will be replaced with its
+ * corresponding value in the destination file.
+ *
+ * @param source the name of to the source template file
+ * @param dest the path to the destination file
+ * @param keywords in the destination file, the keys will be replaced by their values
+ * @param force True to force writing the file even if it already exists
+ * @param outDir the output directory to copy the template file to
+ */
+ private void installBuildTemplate(String source, String dest,
+ Map<String, String> keywords, boolean force, String outDir) {
+ final String sourcePath = mLibDir + File.separator + source;
+ final String destPath = outDir + File.separator + dest;
+
+ installFullPathTemplate(sourcePath, destPath, keywords, force);
+ }
+
+ /**
* Installs a destination file that is based on the template file at source.
* For each match of each key in keywords will be replaced with its
* corresponding value in the destination file.
*
- * @param source the path to the source template file
- * @param dest the path to the destination file
+ * @param sourcePath the full path to the source template file
+ * @param destPath the full path to the destination file
* @param keywords in the destination file, the keys will be replaced by their values
* @param force True to force writing the file even if it already exists
*/
- private void installTemplate(String source, String dest,
+ private void installFullPathTemplate(String sourcePath, String destPath,
Map<String, String> keywords, boolean force) {
- final String sourcePath = mLibDir + File.separator + source;
- final String destPath = mOutDir + File.separator + dest;
-
final File destPathFile = new File(destPath);
if (!force && destPathFile.exists()) {
println("WARNING! The file %1$s already exists and will not be overwritten!\n",
@@ -308,33 +395,19 @@
}
/**
- * Installs a destination file that is based on the template file at source.
- * For each match of each key in keywords will be replaced with its
- * corresponding value in the destination file.
- *
- * This version does NOT install the file if it already exists.
- *
- * @param source the path to the source template file
- * @param dest the path to the destination file
- * @param keywords in the destination file, the keys will be replaced by their values
- */
- private void installTemplate(String source, String dest, Map<String, String> keywords) {
- installTemplate(source, dest, keywords, false /* force */);
- }
-
-
- /**
* Set up the Android-related files
*/
private void setupProject() {
String packageName = null;
String activityName = null;
+ String activityTestName = null;
try {
/* Grab package and Activity names */
int lastPeriod = mPackageFull.lastIndexOf('.');
packageName = mPackageFull.substring(0, lastPeriod);
if (lastPeriod < mPackageFull.length() - 1) {
activityName = mPackageFull.substring(lastPeriod+1);
+ activityTestName = activityName + "Test";
}
if (packageName.indexOf('.') == -1) {
@@ -346,11 +419,20 @@
println("Package: %1$s", packageName);
println("Output directory: %1$s", mOutDir);
+ String testsOutDir = mOutDir + File.separator + "tests";
+ println("Tests directory: %1$s", testsOutDir);
+
if (activityName != null) {
println("Activity name: %1$s", activityName);
}
+ if (activityTestName != null) {
+ println("ActivityTest name: %1$s", activityTestName);
+ }
final HashMap<String, String> keywords = createBaseKeywordMap();
+
+ addTargetKeywords(keywords);
+
keywords.put("PACKAGE", packageName);
if (activityName != null) {
keywords.put("ACTIVITY_NAME", activityName);
@@ -367,40 +449,63 @@
final String srcDir = "src" + File.separator + packagePath;
createDirs(srcDir);
if (isDirEmpty(srcDir, "Java") && activityName != null) {
- installTemplate("java_file.template", srcDir + File.separator
- + activityName + ".java", keywords);
+ installProjectTemplate("java_file.template", srcDir + File.separator
+ + activityName + ".java", keywords, false /*force*/);
}
createDirs("bin");
createDirs("libs");
+ createDirs("res");
+
+ /* Make ActivityTest java file */
+ createDirs(srcDir, testsOutDir);
+ if (isDirEmpty(srcDir, "Java", testsOutDir) && activityTestName != null) {
+ installProjectTemplate("java_tests_file.template", srcDir + File.separator
+ + activityTestName + ".java", keywords, false, testsOutDir);
+ }
+ createDirs("bin", testsOutDir);
+ createDirs("libs", testsOutDir);
+ createDirs("res", testsOutDir);
/* Make res files */
final String valuesDir = "res" + File.separator + "values";
createDirs(valuesDir);
if (isDirEmpty(valuesDir, "Resource Values")) {
- installTemplate("strings.template", valuesDir + File.separator
- + "strings.xml", keywords);
+ installProjectTemplate("strings.template", valuesDir + File.separator
+ + "strings.xml", keywords, false /*force*/);
}
final String layoutDir = "res" + File.separator + "layout";
createDirs(layoutDir);
if (isDirEmpty(layoutDir, "Resource Layout")) {
- installTemplate("layout.template", layoutDir + File.separator
- + "main.xml", keywords);
+ installProjectTemplate("layout.template", layoutDir + File.separator
+ + "main.xml", keywords, false /*force*/);
}
/* Make AndroidManifest.xml and build.xml files */
- installTemplate("AndroidManifest.template", "AndroidManifest.xml",
- keywords);
+ installProjectTemplate("AndroidManifest.template", "AndroidManifest.xml",
+ keywords, false /*force*/);
- installTemplate("build.template", "build.xml", keywords);
- installTemplate("default.properties.template", "default.properties", keywords, true /*force*/);
+ installBuildTemplate("build.template", "build.xml", keywords, false /*force*/);
+ installBuildTemplate("default.properties.template", "default.properties", keywords,
+ true /*force*/);
+
+ /* Make AndroidManifest.xml and build.xml files for tests */
+ installProjectTemplate("AndroidManifest.tests.template", "AndroidManifest.xml",
+ keywords, false /*force*/, testsOutDir);
+
+ installBuildTemplate("build.template", "build.xml", keywords, false /*force*/, testsOutDir);
+ installBuildTemplate("default.properties.template", "default.properties", keywords,
+ true /*force*/, testsOutDir);
if (mIde.equals("intellij")) {
/* IntelliJ files */
if (activityName != null) {
- installTemplate("iml.template", activityName + ".iml", keywords);
- installTemplate("ipr.template", activityName + ".ipr", keywords);
- installTemplate("iws.template", activityName + ".iws", keywords);
+ installProjectTemplate("iml.template", activityName + ".iml", keywords,
+ false /*force*/);
+ installProjectTemplate("ipr.template", activityName + ".ipr", keywords,
+ false /*force*/);
+ installProjectTemplate("iws.template", activityName + ".iws", keywords,
+ false /*force*/);
}
} else if (!isStringEmpty(mIde)) {
println("WARNING: Unknown IDE option \"%1$s\". No IDE files generated.",
@@ -434,22 +539,24 @@
final String xmlDir = "res" + File.separator + "xml";
createDirs(xmlDir);
if (isDirEmpty(xmlDir, "Resource Xml")) {
- installTemplate("alias.template", xmlDir + File.separator + "alias.xml", keywords);
+ installProjectTemplate("alias.template", xmlDir + File.separator + "alias.xml",
+ keywords, false /*force*/);
}
final String valuesDir = "res" + File.separator + "values";
createDirs(valuesDir);
if (isDirEmpty(valuesDir, "Resource Values")) {
- installTemplate("strings.template", valuesDir + File.separator
- + "strings.xml", keywords);
+ installProjectTemplate("strings.template", valuesDir + File.separator
+ + "strings.xml", keywords, false /*force*/);
}
/* Make AndroidManifest.xml and build.xml files */
- installTemplate("AndroidManifest.alias.template", "AndroidManifest.xml", keywords);
+ installProjectTemplate("AndroidManifest.alias.template", "AndroidManifest.xml", keywords,
+ false /*force*/);
- installTemplate("build.alias.template", "build.xml", keywords);
- installTemplate("default.properties.template", "default.properties", keywords, true /*force*/);
+ installBuildTemplate("build.alias.template", "build.xml", keywords, false /*force*/);
+ installBuildTemplate("default.properties.template", "default.properties", keywords, true /*force*/);
}
@@ -467,6 +574,16 @@
return keywords;
}
+
+ private void addTargetKeywords(HashMap<String, String> keywords) {
+ // FIXME: get this from the target selection
+ keywords.put("TARGET_MODE", "platform");
+ keywords.put("TARGET_API", "1"); // this is potentially wrong but since it's only used
+ // when editing a project config, this is ok for now.
+ keywords.put("TARGET_NAME", "android"); // this is only used in add-on mode.
+ keywords.put("TARGET_FOLDER", mTargetPlatform);
+ keywords.put("TARGET_MODE", "platform");
+ }
/**
@@ -500,10 +617,27 @@
/**
* Creates the path in the output directory along with any parent paths
* that don't exist.
+ *
+ * Invokes ActivityCreator#createDirs(String, String) with
+ * the main project output directory (#mOutDir) as the last argument.
+ *
* @param path the directory out/path that is created.
+ *
+ * @see com.android.activitycreator.ActivityCreator#createDirs(String, String)
*/
public void createDirs(String path) {
- final File pathFile = new File(mOutDir + File.separator + path);
+ createDirs(path, mOutDir);
+ }
+
+ /**
+ * Creates the path in the output directory along with any parent paths
+ * that don't exist.
+ *
+ * @param path the directory out/path that is created.
+ * @param dir the directory in which the path to be created
+ */
+ public void createDirs(String path, String dir) {
+ final File pathFile = new File(dir + File.separator + path);
boolean existedBefore = true;
if (!pathFile.exists()) {
@@ -529,28 +663,45 @@
}
}
}
-
+
/**
* Checks whether the path in the output directory is empty
- *
+ *
+ * Invokes ActivityCreator#isDirEmpty(String, String, String) with
+ * the main project output directory (#mOutDir) as the last argument.
+ *
* @param path the out/path directory that is checked
* @param message the logical name for what this path points to (used in
* warning message)
* @return whether the directory is empty
+ * @see com.android.activitycreator.ActivityCreator#isDirEmpty(String, String, String)
*/
public boolean isDirEmpty(String path, String message) {
- File pathFile = new File(mOutDir + File.separator + path);
-
+ return isDirEmpty(path, message, mOutDir);
+ }
+
+ /**
+ * Checks whether the path in the output directory is empty
+ *
+ * @param path the out/path directory that is checked
+ * @param message the logical name for what this path points to (used in
+ * warning message)
+ * @param outDir the output director to check
+ * @return whether the directory is empty
+ */
+ public boolean isDirEmpty(String path, String message, String outDir) {
+ File pathFile = new File(outDir + File.separator + path);
+
String[] pathListing = pathFile.list();
if ((pathListing != null) && (pathListing.length > 0)) {
println("WARNING: There are already some %1$s files present. None will be created!",
message);
return false;
}
-
+
return true;
}
-
+
/**
* Strips the string of beginning and trailing characters (multiple
* characters will be stripped, example stripString("..test...", '.')
@@ -588,9 +739,10 @@
* Returns true if the project is an alias project.
* <p/>
* Alias projects require both the --url and the --label options.
+ * @return boolean true if the project requested is an alias project
*/
private boolean isAliasProject() {
- return (isStringEmpty(mAliasData) == false && isStringEmpty(mApplicationLabel) == false);
+ return (!isStringEmpty(mAliasData) && !isStringEmpty(mApplicationLabel));
}
/**
diff --git a/tools/androidprefs/src/com/android/prefs/AndroidLocation.java b/tools/androidprefs/src/com/android/prefs/AndroidLocation.java
index 28e10dd..3530f2d 100644
--- a/tools/androidprefs/src/com/android/prefs/AndroidLocation.java
+++ b/tools/androidprefs/src/com/android/prefs/AndroidLocation.java
@@ -32,6 +32,11 @@
private static final String ANDROID_SDK_VERSION = "SDK-1.0";
/**
+ * VM folder inside the path returned by {@link #getFolder()}
+ */
+ public static final String FOLDER_VMS = "vm";
+
+ /**
* Throw when the location of the android folder couldn't be found.
*/
public static final class AndroidLocationException extends Exception {
diff --git a/tools/apkbuilder/src/com/android/apkbuilder/ApkBuilder.java b/tools/apkbuilder/src/com/android/apkbuilder/ApkBuilder.java
index 0f31ef5..9a4d24b 100644
--- a/tools/apkbuilder/src/com/android/apkbuilder/ApkBuilder.java
+++ b/tools/apkbuilder/src/com/android/apkbuilder/ApkBuilder.java
@@ -335,8 +335,9 @@
DebugKeyProvider.getDefaultKeyStoreOsPath()));
- DebugKeyProvider keyProvider = new DebugKeyProvider(storeType,
- null /* IKeyGenOutput */);
+ DebugKeyProvider keyProvider = new DebugKeyProvider(
+ null /* osKeyPath: use default */,
+ storeType, null /* IKeyGenOutput */);
PrivateKey key = keyProvider.getDebugKey();
X509Certificate certificate = (X509Certificate)keyProvider.getCertificate();
diff --git a/tools/ddms/app/.classpath b/tools/ddms/app/.classpath
index ad40766..2fa1fb7 100644
--- a/tools/ddms/app/.classpath
+++ b/tools/ddms/app/.classpath
@@ -2,10 +2,10 @@
<classpath>
<classpathentry excluding="Makefile|resources/" kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry combineaccessrules="false" kind="src" path="/PingService"/>
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/ANDROID_SWT"/>
<classpathentry combineaccessrules="false" kind="src" path="/ddmlib"/>
<classpathentry combineaccessrules="false" kind="src" path="/ddmuilib"/>
<classpathentry combineaccessrules="false" kind="src" path="/AndroidPrefs"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/SdkStatsService"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/ClientData.java b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/ClientData.java
index 230bdf0..2b46b6f 100644
--- a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/ClientData.java
+++ b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/ClientData.java
@@ -103,7 +103,7 @@
private boolean mIsDdmAware;
// the client's process ID
- private int mPid = -1;
+ private final int mPid;
// Java VM identification string
private String mVmIdentifier;
@@ -273,14 +273,6 @@
}
/**
- * Sets process ID.
- */
- void setPid(int pid) {
- assert pid != mPid;
- mPid = pid;
- }
-
- /**
* Returns the Client's VM identifier.
*/
public String getVmIdentifier() {
diff --git a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/Device.java b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/Device.java
index bad68af..a031a1b 100644
--- a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/Device.java
+++ b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/Device.java
@@ -30,8 +30,10 @@
/**
* A Device. It can be a physical device or an emulator.
+ *
+ * TODO: make this class package-protected, and shift all callers to use IDevice
*/
-public final class Device {
+public final class Device implements IDevice {
/**
* The state of a device.
*/
@@ -61,22 +63,9 @@
}
}
- public final static String PROP_BUILD_VERSION = "ro.build.version.release";
- public final static String PROP_DEBUGGABLE = "ro.debuggable";
-
- /** Serial number of the first connected emulator. */
- public final static String FIRST_EMULATOR_SN = "emulator-5554"; //$NON-NLS-1$
-
/** Emulator Serial Number regexp. */
final static String RE_EMULATOR_SN = "emulator-(\\d+)"; //$NON-NLS-1$
- /** Device change bit mask: {@link DeviceState} change. */
- public static final int CHANGE_STATE = 0x0001;
- /** Device change bit mask: {@link Client} list change. */
- public static final int CHANGE_CLIENT_LIST = 0x0002;
- /** Device change bit mask: build info change. */
- public static final int CHANGE_BUILD_INFO = 0x0004;
-
/** Serial number of the device */
String serialNumber = null;
@@ -94,38 +83,41 @@
*/
private SocketChannel mSocketChannel;
- /**
- * Returns the serial number of the device.
+ /*
+ * (non-Javadoc)
+ * @see com.android.ddmlib.IDevice#getSerialNumber()
*/
public String getSerialNumber() {
return serialNumber;
}
- /**
- * Returns the state of the device.
+ /*
+ * (non-Javadoc)
+ * @see com.android.ddmlib.IDevice#getState()
*/
public DeviceState getState() {
return state;
}
- /**
- * Returns the device properties. It contains the whole output of 'getprop'
+ /*
+ * (non-Javadoc)
+ * @see com.android.ddmlib.IDevice#getProperties()
*/
public Map<String, String> getProperties() {
return Collections.unmodifiableMap(mProperties);
}
- /**
- * Returns the number of property for this device.
+ /*
+ * (non-Javadoc)
+ * @see com.android.ddmlib.IDevice#getPropertyCount()
*/
public int getPropertyCount() {
return mProperties.size();
}
- /**
- * Returns a property value.
- * @param name the name of the value to return.
- * @return the value or <code>null</code> if the property does not exist.
+ /*
+ * (non-Javadoc)
+ * @see com.android.ddmlib.IDevice#getProperty(java.lang.String)
*/
public String getProperty(String name) {
return mProperties.get(name);
@@ -137,46 +129,49 @@
return serialNumber;
}
- /**
- * Returns if the device is ready.
- * @return <code>true</code> if {@link #getState()} returns {@link DeviceState#ONLINE}.
+ /*
+ * (non-Javadoc)
+ * @see com.android.ddmlib.IDevice#isOnline()
*/
public boolean isOnline() {
return state == DeviceState.ONLINE;
}
- /**
- * Returns <code>true</code> if the device is an emulator.
+ /*
+ * (non-Javadoc)
+ * @see com.android.ddmlib.IDevice#isEmulator()
*/
public boolean isEmulator() {
return serialNumber.matches(RE_EMULATOR_SN);
}
- /**
- * Returns if the device is offline.
- * @return <code>true</code> if {@link #getState()} returns {@link DeviceState#OFFLINE}.
+ /*
+ * (non-Javadoc)
+ * @see com.android.ddmlib.IDevice#isOffline()
*/
public boolean isOffline() {
return state == DeviceState.OFFLINE;
}
- /**
- * Returns if the device is in bootloader mode.
- * @return <code>true</code> if {@link #getState()} returns {@link DeviceState#BOOTLOADER}.
+ /*
+ * (non-Javadoc)
+ * @see com.android.ddmlib.IDevice#isBootLoader()
*/
public boolean isBootLoader() {
return state == DeviceState.BOOTLOADER;
}
- /**
- * Returns whether the {@link Device} has {@link Client}s.
+ /*
+ * (non-Javadoc)
+ * @see com.android.ddmlib.IDevice#hasClients()
*/
public boolean hasClients() {
return mClients.size() > 0;
}
- /**
- * Returns the array of clients.
+ /*
+ * (non-Javadoc)
+ * @see com.android.ddmlib.IDevice#getClients()
*/
public Client[] getClients() {
synchronized (mClients) {
@@ -184,10 +179,9 @@
}
}
- /**
- * Returns a {@link Client} by its application name.
- * @param applicationName the name of the application
- * @return the <code>Client</code> object or <code>null</code> if no match was found.
+ /*
+ * (non-Javadoc)
+ * @see com.android.ddmlib.IDevice#getClient(java.lang.String)
*/
public Client getClient(String applicationName) {
synchronized (mClients) {
@@ -202,9 +196,9 @@
return null;
}
- /**
- * Returns a {@link SyncService} object to push / pull files to and from the device.
- * @return <code>null</code> if the SyncService couldn't be created.
+ /*
+ * (non-Javadoc)
+ * @see com.android.ddmlib.IDevice#getSyncService()
*/
public SyncService getSyncService() {
SyncService syncService = new SyncService(AndroidDebugBridge.sSocketAddr, this);
@@ -215,28 +209,25 @@
return null;
}
- /**
- * Returns a {@link FileListingService} for this device.
+ /*
+ * (non-Javadoc)
+ * @see com.android.ddmlib.IDevice#getFileListingService()
*/
public FileListingService getFileListingService() {
return new FileListingService(this);
}
- /**
- * Takes a screen shot of the device and returns it as a {@link RawImage}.
- * @return the screenshot as a <code>RawImage</code> or <code>null</code> if
- * something went wrong.
- * @throws IOException
+ /*
+ * (non-Javadoc)
+ * @see com.android.ddmlib.IDevice#getScreenshot()
*/
public RawImage getScreenshot() throws IOException {
return AdbHelper.getFrameBuffer(AndroidDebugBridge.sSocketAddr, this);
}
- /**
- * Executes a shell command on the device, and sends the result to a receiver.
- * @param command The command to execute
- * @param receiver The receiver object getting the result from the command.
- * @throws IOException
+ /*
+ * (non-Javadoc)
+ * @see com.android.ddmlib.IDevice#executeShellCommand(java.lang.String, com.android.ddmlib.IShellOutputReceiver)
*/
public void executeShellCommand(String command, IShellOutputReceiver receiver)
throws IOException {
@@ -244,20 +235,17 @@
receiver);
}
- /**
- * Runs the event log service and outputs the event log to the {@link LogReceiver}.
- * @param receiver the receiver to receive the event log entries.
- * @throws IOException
+ /*
+ * (non-Javadoc)
+ * @see com.android.ddmlib.IDevice#runEventLogService(com.android.ddmlib.log.LogReceiver)
*/
public void runEventLogService(LogReceiver receiver) throws IOException {
AdbHelper.runEventLogService(AndroidDebugBridge.sSocketAddr, this, receiver);
}
- /**
- * Creates a port forwarding between a local and a remote port.
- * @param localPort the local port to forward
- * @param remotePort the remote port.
- * @return <code>true</code> if success.
+ /*
+ * (non-Javadoc)
+ * @see com.android.ddmlib.IDevice#createForward(int, int)
*/
public boolean createForward(int localPort, int remotePort) {
try {
@@ -269,11 +257,9 @@
}
}
- /**
- * Removes a port forwarding between a local and a remote port.
- * @param localPort the local port to forward
- * @param remotePort the remote port.
- * @return <code>true</code> if success.
+ /*
+ * (non-Javadoc)
+ * @see com.android.ddmlib.IDevice#removeForward(int, int)
*/
public boolean removeForward(int localPort, int remotePort) {
try {
@@ -285,9 +271,9 @@
}
}
- /**
- * Returns the name of the client by pid or <code>null</code> if pid is unknown
- * @param pid the pid of the client.
+ /*
+ * (non-Javadoc)
+ * @see com.android.ddmlib.IDevice#getClientName(int)
*/
public String getClientName(int pid) {
synchronized (mClients) {
diff --git a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHello.java b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHello.java
index 3b4825a..5ba5aeb 100644
--- a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHello.java
+++ b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHello.java
@@ -84,16 +84,21 @@
vmIdent = getString(data, vmIdentLen);
appName = getString(data, appNameLen);
-
+
Log.d("ddm-hello", "HELO: v=" + version + ", pid=" + pid
+ ", vm='" + vmIdent + "', app='" + appName + "'");
ClientData cd = client.getClientData();
+
synchronized (cd) {
- cd.setVmIdentifier(vmIdent);
- cd.setClientDescription(appName);
- cd.setPid(pid);
- cd.isDdmAware(true);
+ if (cd.getPid() == pid) {
+ cd.setVmIdentifier(vmIdent);
+ cd.setClientDescription(appName);
+ cd.isDdmAware(true);
+ } else {
+ Log.e("ddm-hello", "Received pid (" + pid + ") does not match client pid ("
+ + cd.getPid() + ")");
+ }
}
client = checkDebuggerPortForAppName(client, appName);
diff --git a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/IDevice.java b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/IDevice.java
new file mode 100755
index 0000000..106b76f
--- /dev/null
+++ b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/IDevice.java
@@ -0,0 +1,167 @@
+/*
+ * 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.ddmlib;
+
+import com.android.ddmlib.Device.DeviceState;
+import com.android.ddmlib.log.LogReceiver;
+
+import java.io.IOException;
+import java.util.Map;
+
+
+/**
+ * A Device. It can be a physical device or an emulator.
+ */
+public interface IDevice {
+
+ public final static String PROP_BUILD_VERSION = "ro.build.version.release";
+ public final static String PROP_BUILD_VERSION_NUMBER = "ro.build.version.sdk";
+ public final static String PROP_DEBUGGABLE = "ro.debuggable";
+ /** Serial number of the first connected emulator. */
+ public final static String FIRST_EMULATOR_SN = "emulator-5554"; //$NON-NLS-1$
+ /** Device change bit mask: {@link DeviceState} change. */
+ public static final int CHANGE_STATE = 0x0001;
+ /** Device change bit mask: {@link Client} list change. */
+ public static final int CHANGE_CLIENT_LIST = 0x0002;
+ /** Device change bit mask: build info change. */
+ public static final int CHANGE_BUILD_INFO = 0x0004;
+
+ /**
+ * Returns the serial number of the device.
+ */
+ public String getSerialNumber();
+
+ /**
+ * Returns the state of the device.
+ */
+ public DeviceState getState();
+
+ /**
+ * Returns the device properties. It contains the whole output of 'getprop'
+ */
+ public Map<String, String> getProperties();
+
+ /**
+ * Returns the number of property for this device.
+ */
+ public int getPropertyCount();
+
+ /**
+ * Returns a property value.
+ * @param name the name of the value to return.
+ * @return the value or <code>null</code> if the property does not exist.
+ */
+ public String getProperty(String name);
+
+ /**
+ * Returns if the device is ready.
+ * @return <code>true</code> if {@link #getState()} returns {@link DeviceState#ONLINE}.
+ */
+ public boolean isOnline();
+
+ /**
+ * Returns <code>true</code> if the device is an emulator.
+ */
+ public boolean isEmulator();
+
+ /**
+ * Returns if the device is offline.
+ * @return <code>true</code> if {@link #getState()} returns {@link DeviceState#OFFLINE}.
+ */
+ public boolean isOffline();
+
+ /**
+ * Returns if the device is in bootloader mode.
+ * @return <code>true</code> if {@link #getState()} returns {@link DeviceState#BOOTLOADER}.
+ */
+ public boolean isBootLoader();
+
+ /**
+ * Returns whether the {@link Device} has {@link Client}s.
+ */
+ public boolean hasClients();
+
+ /**
+ * Returns the array of clients.
+ */
+ public Client[] getClients();
+
+ /**
+ * Returns a {@link Client} by its application name.
+ * @param applicationName the name of the application
+ * @return the <code>Client</code> object or <code>null</code> if no match was found.
+ */
+ public Client getClient(String applicationName);
+
+ /**
+ * Returns a {@link SyncService} object to push / pull files to and from the device.
+ * @return <code>null</code> if the SyncService couldn't be created.
+ */
+ public SyncService getSyncService();
+
+ /**
+ * Returns a {@link FileListingService} for this device.
+ */
+ public FileListingService getFileListingService();
+
+ /**
+ * Takes a screen shot of the device and returns it as a {@link RawImage}.
+ * @return the screenshot as a <code>RawImage</code> or <code>null</code> if
+ * something went wrong.
+ * @throws IOException
+ */
+ public RawImage getScreenshot() throws IOException;
+
+ /**
+ * Executes a shell command on the device, and sends the result to a receiver.
+ * @param command The command to execute
+ * @param receiver The receiver object getting the result from the command.
+ * @throws IOException
+ */
+ public void executeShellCommand(String command,
+ IShellOutputReceiver receiver) throws IOException;
+
+ /**
+ * Runs the event log service and outputs the event log to the {@link LogReceiver}.
+ * @param receiver the receiver to receive the event log entries.
+ * @throws IOException
+ */
+ public void runEventLogService(LogReceiver receiver) throws IOException;
+
+ /**
+ * Creates a port forwarding between a local and a remote port.
+ * @param localPort the local port to forward
+ * @param remotePort the remote port.
+ * @return <code>true</code> if success.
+ */
+ public boolean createForward(int localPort, int remotePort);
+
+ /**
+ * Removes a port forwarding between a local and a remote port.
+ * @param localPort the local port to forward
+ * @param remotePort the remote port.
+ * @return <code>true</code> if success.
+ */
+ public boolean removeForward(int localPort, int remotePort);
+
+ /**
+ * Returns the name of the client by pid or <code>null</code> if pid is unknown
+ * @param pid the pid of the client.
+ */
+ public String getClientName(int pid);
+
+}
diff --git a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/NativeAllocationInfo.java b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/NativeAllocationInfo.java
index 85e3757..956b004 100644
--- a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/NativeAllocationInfo.java
+++ b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/NativeAllocationInfo.java
@@ -48,6 +48,8 @@
sAllocFunctionFilter.add("operator new"); //$NON-NLS-1$
sAllocFunctionFilter.add("leak_free"); //$NON-NLS-1$
sAllocFunctionFilter.add("chk_free"); //$NON-NLS-1$
+ sAllocFunctionFilter.add("chk_memalign"); //$NON-NLS-1$
+ sAllocFunctionFilter.add("Malloc"); //$NON-NLS-1$
}
private final int mSize;
diff --git a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/log/EventLogParser.java b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/log/EventLogParser.java
index 1974441..85e99c1 100644
--- a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/log/EventLogParser.java
+++ b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/log/EventLogParser.java
@@ -228,6 +228,9 @@
// just ignore this description if data type and data unit don't match
// TODO: log the error.
}
+ } else {
+ Log.e("EventLogParser", //$NON-NLS-1$
+ String.format("Can't parse %1$s", description)); //$NON-NLS-1$
}
}
diff --git a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/testrunner/ITestRunListener.java b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/testrunner/ITestRunListener.java
new file mode 100644
index 0000000..4c0d9de
--- /dev/null
+++ b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/testrunner/ITestRunListener.java
@@ -0,0 +1,72 @@
+/*
+ * 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.ddmlib.testrunner;
+
+/**
+ * Listener for instrumentation test runs
+ *
+ * Modeled after junit.runner.TestRunListener
+ */
+public interface ITestRunListener {
+ public static final int STATUS_ERROR = 1;
+ public static final int STATUS_FAILURE = 2;
+
+ /**
+ * Reports the start of a test run
+ * @param testCount - total number of tests in test run
+ * */
+ public void testRunStarted(int testCount);
+
+ /**
+ * Reports end of test run
+ * @param elapsedTime - device reported elapsed time, in milliseconds
+ */
+ public void testRunEnded(long elapsedTime);
+
+ /**
+ * Reports test run stopped before completion
+ * @param elapsedTime - device reported elapsed time, in milliseconds
+ */
+ public void testRunStopped(long elapsedTime);
+
+ /**
+ * Reports the start of an individual test case
+ */
+ public void testStarted(String className, String testName);
+
+ /**
+ * Reports the execution end of an individual test case
+ * If no testFailed has been reported, this is a passed test
+ */
+ public void testEnded(String className, String testName);
+
+ /**
+ * Reports the failure of a individual test case
+ * Will be called between testStarted and testEnded
+ *
+ * @param status - one of STATUS_ERROR, STATUS_FAILURE
+ * @param className - name of test class
+ * @param testName - name of test method
+ * @param trace - stack trace of failure
+ */
+ public void testFailed(int status, String className, String testName, String trace);
+
+ /**
+ * Reports test run failed to execute due to a fatal error
+ */
+ public void testRunFailed(String errorMessage);
+}
diff --git a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/testrunner/InstrumentationResultParser.java b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/testrunner/InstrumentationResultParser.java
new file mode 100755
index 0000000..d47bd56
--- /dev/null
+++ b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/testrunner/InstrumentationResultParser.java
@@ -0,0 +1,327 @@
+/*
+ * 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.ddmlib.testrunner;
+
+import com.android.ddmlib.IShellOutputReceiver;
+import com.android.ddmlib.Log;
+import com.android.ddmlib.MultiLineReceiver;
+
+import java.util.Hashtable;
+import java.util.Map;
+
+/**
+ * Parses the 'raw output mode' results of an instrument test run from shell, and informs a
+ * ITestRunListener of the results
+ *
+ * Expects the following output:
+ *
+ * If fatal error occurred when attempted to run the tests:
+ * <i> INSTRUMENTATION_FAILED: </i>
+ *
+ * Otherwise, expect a series of test results, each one containing a set of status key/value
+ * pairs, delimited by a start(1)/pass(0)/fail(-2)/error(-1) status code result. At end of test
+ * run, expects that the elapsed test time in seconds will be displayed
+ *
+ * i.e.
+ * <i>
+ * INSTRUMENTATION_STATUS_CODE: 1
+ * INSTRUMENTATION_STATUS: class=com.foo.FooTest
+ * INSTRUMENTATION_STATUS: test=testFoo
+ * INSTRUMENTATION_STATUS: numtests=2
+ * INSTRUMENTATION_STATUS: stack=com.foo.FooTest#testFoo:312
+ * com.foo.X
+ * INSTRUMENTATION_STATUS_CODE: -2
+ * ...
+ *
+ * Time: X
+ * </i>
+ *
+ * Note that the "value" portion of the key-value pair may wrap over several text lines
+ */
+public class InstrumentationResultParser extends MultiLineReceiver {
+
+ // relevant test status keys
+ private static final String CODE_KEY = "code";
+ private static final String TEST_KEY = "test";
+ private static final String CLASS_KEY = "class";
+ private static final String STACK_KEY = "stack";
+ private static final String NUMTESTS_KEY = "numtests";
+
+ // test result status codes
+ private static final int FAILURE_STATUS_CODE = -2;
+ private static final int START_STATUS_CODE = 1;
+ private static final int ERROR_STATUS_CODE = -1;
+ private static final int OK_STATUS_CODE = 0;
+
+ // recognized output patterns
+ private static final String STATUS_PREFIX = "INSTRUMENTATION_STATUS: ";
+ private static final String STATUS_PREFIX_CODE = "INSTRUMENTATION_STATUS_CODE: ";
+ private static final String STATUS_FAILED = "INSTRUMENTATION_FAILED: ";
+ private static final String TIME_REPORT = "Time: ";
+
+ private final ITestRunListener mTestListener;
+ /** key-value map for current test */
+ private Map<String, String> mStatusValues;
+ /** stores the current "key" portion of the status key-value being parsed */
+ private String mCurrentKey;
+ /** stores the current "value" portion of the status key-value being parsed */
+ private StringBuilder mCurrentValue;
+ /** true if start of test has already been reported to listener */
+ private boolean mTestStartReported;
+ /** the elapsed time of the test run, in ms */
+ private long mTestTime;
+ /** true if current test run has been canceled by user */
+ private boolean mIsCancelled;
+
+ private static final String LOG_TAG = "InstrumentationResultParser";
+
+ /**
+ * Creates the InstrumentationResultParser
+ * @param listener - listener to report results to. will be informed of test results as the
+ * tests are executing
+ */
+ public InstrumentationResultParser(ITestRunListener listener) {
+ mStatusValues = new Hashtable<String, String>();
+ mCurrentKey = null;
+ setTrimLine(false);
+ mTestListener = listener;
+ mTestStartReported = false;
+ mTestTime = 0;
+ mIsCancelled = false;
+ }
+
+ /**
+ * Processes the instrumentation test output from shell
+ * @see MultiLineReceiver#processNewLines
+ */
+ @Override
+ public void processNewLines(String[] lines) {
+ for (String line : lines) {
+ parse(line);
+ }
+ }
+
+ /**
+ * Parse an individual output line. Expects a line that either is:
+ * a) the start of a new status line (ie. starts with STATUS_PREFIX or STATUS_PREFIX_CODE),
+ * and thus there is a new key=value pair to parse, and the previous key-value pair is
+ * finished
+ * b) a continuation of the previous status (ie the "value" portion of the key has wrapped
+ * to the next line.
+ * c) a line reporting a fatal error in the test run (STATUS_FAILED)
+ * d) a line reporting the total elapsed time of the test run.
+ *
+ * @param line - text output line
+ */
+ private void parse(String line) {
+ if (line.startsWith(STATUS_PREFIX_CODE)) {
+ // Previous status key-value has been collected. Store it.
+ submitCurrentKeyValue();
+ parseStatusCode(line);
+ } else if (line.startsWith(STATUS_PREFIX)) {
+ // Previous status key-value has been collected. Store it.
+ submitCurrentKeyValue();
+ parseKey(line, STATUS_PREFIX.length());
+ } else if (line.startsWith(STATUS_FAILED)) {
+ Log.e(LOG_TAG, "test run failed " + line);
+ mTestListener.testRunFailed(line);
+ } else if (line.startsWith(TIME_REPORT)) {
+ parseTime(line, TIME_REPORT.length());
+ } else {
+ if (mCurrentValue != null) {
+ // this is a value that has wrapped to next line.
+ mCurrentValue.append("\r\n");
+ mCurrentValue.append(line);
+ } else {
+ Log.w(LOG_TAG, "unrecognized line " + line);
+ }
+ }
+ }
+
+ /**
+ * Stores the currently parsed key-value pair in the status map
+ */
+ private void submitCurrentKeyValue() {
+ if (mCurrentKey != null && mCurrentValue != null) {
+ mStatusValues.put(mCurrentKey, mCurrentValue.toString());
+ mCurrentKey = null;
+ mCurrentValue = null;
+ }
+ }
+
+ /**
+ * Parses the key from the current line
+ * Expects format of "key=value",
+ * @param line - full line of text to parse
+ * @param keyStartPos - the starting position of the key in the given line
+ */
+ private void parseKey(String line, int keyStartPos) {
+ int endKeyPos = line.indexOf('=', keyStartPos);
+ if (endKeyPos != -1) {
+ mCurrentKey = line.substring(keyStartPos, endKeyPos).trim();
+ parseValue(line, endKeyPos+1);
+ }
+ }
+
+ /**
+ * Parses the start of a key=value pair.
+ * @param line - full line of text to parse
+ * @param valueStartPos - the starting position of the value in the given line
+ */
+ private void parseValue(String line, int valueStartPos) {
+ mCurrentValue = new StringBuilder();
+ mCurrentValue.append(line.substring(valueStartPos));
+ }
+
+ /**
+ * Parses out a status code result. For consistency, stores the result as a CODE entry in
+ * key-value status map
+ */
+ private void parseStatusCode(String line) {
+ String value = line.substring(STATUS_PREFIX_CODE.length()).trim();
+ mStatusValues.put(CODE_KEY, value);
+
+ // this means we're done with current test result bundle
+ reportResult(mStatusValues);
+ mStatusValues.clear();
+ }
+
+ /**
+ * Returns true if test run canceled
+ *
+ * @see IShellOutputReceiver#isCancelled()
+ */
+ public boolean isCancelled() {
+ return mIsCancelled;
+ }
+
+ /**
+ * Requests cancellation of test result parsing
+ */
+ public void cancel() {
+ mIsCancelled = true;
+ }
+
+ /**
+ * Reports a test result to the test run listener. Must be called when a individual test
+ * result has been fully parsed.
+ * @param statusMap - key-value status pairs of test result
+ */
+ private void reportResult(Map<String, String> statusMap) {
+ String className = statusMap.get(CLASS_KEY);
+ String testName = statusMap.get(TEST_KEY);
+ String statusCodeString = statusMap.get(CODE_KEY);
+
+ if (className == null || testName == null || statusCodeString == null) {
+ Log.e(LOG_TAG, "invalid instrumentation status bundle " + statusMap.toString());
+ return;
+ }
+ className = className.trim();
+ testName = testName.trim();
+
+ reportTestStarted(statusMap);
+
+ try {
+ int statusCode = Integer.parseInt(statusCodeString);
+
+ switch (statusCode) {
+ case START_STATUS_CODE:
+ mTestListener.testStarted(className, testName);
+ break;
+ case FAILURE_STATUS_CODE:
+ mTestListener.testFailed(ITestRunListener.STATUS_FAILURE, className, testName,
+ getTrace(statusMap));
+ mTestListener.testEnded(className, testName);
+ break;
+ case ERROR_STATUS_CODE:
+ mTestListener.testFailed(ITestRunListener.STATUS_ERROR, className, testName,
+ getTrace(statusMap));
+ mTestListener.testEnded(className, testName);
+ break;
+ case OK_STATUS_CODE:
+ mTestListener.testEnded(className, testName);
+ break;
+ default:
+ Log.e(LOG_TAG, "Expected status code, received: " + statusCodeString);
+ mTestListener.testEnded(className, testName);
+ break;
+ }
+ }
+ catch (NumberFormatException e) {
+ Log.e(LOG_TAG, "Expected integer status code, received: " + statusCodeString);
+ }
+ }
+
+ /**
+ * Reports the start of a test run, and the total test count, if it has not been previously
+ * reported
+ * @param statusMap - key-value status pairs
+ */
+ private void reportTestStarted(Map<String, String> statusMap) {
+ // if start test run not reported yet
+ if (!mTestStartReported) {
+ String numTestsString = statusMap.get(NUMTESTS_KEY);
+ if (numTestsString != null) {
+ try {
+ int numTests = Integer.parseInt(numTestsString);
+ mTestListener.testRunStarted(numTests);
+ mTestStartReported = true;
+ }
+ catch (NumberFormatException e) {
+ Log.e(LOG_TAG, "Unexpected numTests format " + numTestsString);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the stack trace of the current failed test, from the provided key-value status map
+ */
+ private String getTrace(Map<String, String> statusMap) {
+ String stackTrace = statusMap.get(STACK_KEY);
+ if (stackTrace != null) {
+ return stackTrace;
+ }
+ else {
+ Log.e(LOG_TAG, "Could not find stack trace for failed test ");
+ return new Throwable("Unknown failure").toString();
+ }
+ }
+
+ /**
+ * Parses out and store the elapsed time
+ */
+ private void parseTime(String line, int startPos) {
+ String timeString = line.substring(startPos);
+ try {
+ float timeSeconds = Float.parseFloat(timeString);
+ mTestTime = (long)(timeSeconds * 1000);
+ }
+ catch (NumberFormatException e) {
+ Log.e(LOG_TAG, "Unexpected time format " + timeString);
+ }
+ }
+
+ /**
+ * Called by parent when adb session is complete.
+ */
+ @Override
+ public void done() {
+ super.done();
+ mTestListener.testRunEnded(mTestTime);
+ }
+}
diff --git a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/testrunner/RemoteAndroidTestRunner.java b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/testrunner/RemoteAndroidTestRunner.java
new file mode 100644
index 0000000..5de632e
--- /dev/null
+++ b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/testrunner/RemoteAndroidTestRunner.java
@@ -0,0 +1,221 @@
+/*
+ * 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.ddmlib.testrunner;
+
+
+import com.android.ddmlib.IDevice;
+import com.android.ddmlib.Log;
+
+import java.io.IOException;
+
+/**
+ * Runs a Android test command remotely and reports results
+ */
+public class RemoteAndroidTestRunner {
+
+ private static final char CLASS_SEPARATOR = ',';
+ private static final char METHOD_SEPARATOR = '#';
+ private static final char RUNNER_SEPARATOR = '/';
+ private String mClassArg;
+ private final String mPackageName;
+ private final String mRunnerName;
+ private String mExtraArgs;
+ private boolean mLogOnlyMode;
+ private IDevice mRemoteDevice;
+ private InstrumentationResultParser mParser;
+
+ private static final String LOG_TAG = "RemoteAndroidTest";
+ private static final String DEFAULT_RUNNER_NAME =
+ "android.test.InstrumentationTestRunner";
+
+ /**
+ * Creates a remote android test runner.
+ * @param packageName - the Android application package that contains the tests to run
+ * @param runnerName - the instrumentation test runner to execute. If null, will use default
+ * runner
+ * @param remoteDevice - the Android device to execute tests on
+ */
+ public RemoteAndroidTestRunner(String packageName,
+ String runnerName,
+ IDevice remoteDevice) {
+
+ mPackageName = packageName;
+ mRunnerName = runnerName;
+ mRemoteDevice = remoteDevice;
+ mClassArg = null;
+ mExtraArgs = "";
+ mLogOnlyMode = false;
+ }
+
+ /**
+ * Alternate constructor. Uses default instrumentation runner
+ * @param packageName - the Android application package that contains the tests to run
+ * @param remoteDevice - the Android device to execute tests on
+ */
+ public RemoteAndroidTestRunner(String packageName,
+ IDevice remoteDevice) {
+ this(packageName, null, remoteDevice);
+ }
+
+ /**
+ * Returns the application package name
+ */
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ /**
+ * Returns the runnerName
+ */
+ public String getRunnerName() {
+ if (mRunnerName == null) {
+ return DEFAULT_RUNNER_NAME;
+ }
+ return mRunnerName;
+ }
+
+ /**
+ * Returns the complete instrumentation component path
+ */
+ private String getRunnerPath() {
+ return getPackageName() + RUNNER_SEPARATOR + getRunnerName();
+ }
+
+ /**
+ * Sets to run only tests in this class
+ * Must be called before 'run'
+ * @param className - fully qualified class name (eg x.y.z)
+ */
+ public void setClassName(String className) {
+ mClassArg = className;
+ }
+
+ /**
+ * Sets to run only tests in the provided classes
+ * Must be called before 'run'
+ * If providing more than one class, requires a InstrumentationTestRunner that supports
+ * the multiple class argument syntax
+ * @param classNames - array of fully qualified class name (eg x.y.z)
+ */
+ public void setClassNames(String[] classNames) {
+ StringBuilder classArgBuilder = new StringBuilder();
+
+ for (int i=0; i < classNames.length; i++) {
+ if (i != 0) {
+ classArgBuilder.append(CLASS_SEPARATOR);
+ }
+ classArgBuilder.append(classNames[i]);
+ }
+ mClassArg = classArgBuilder.toString();
+ }
+
+ /**
+ * Sets to run only specified test method
+ * Must be called before 'run'
+ * @param className - fully qualified class name (eg x.y.z)
+ * @param testName - method name
+ */
+ public void setMethodName(String className, String testName) {
+ mClassArg = className + METHOD_SEPARATOR + testName;
+ }
+
+ /**
+ * Sets extra arguments to include in instrumentation command.
+ * Must be called before 'run'
+ * @param instrumentationArgs - must not be null
+ */
+ public void setExtraArgs(String instrumentationArgs) {
+ if (instrumentationArgs == null) {
+ throw new IllegalArgumentException("instrumentationArgs cannot be null");
+ }
+ mExtraArgs = instrumentationArgs;
+ }
+
+ /**
+ * Returns the extra instrumentation arguments
+ */
+ public String getExtraArgs() {
+ return mExtraArgs;
+ }
+
+ /**
+ * Sets this test run to log only mode - skips test execution
+ */
+ public void setLogOnly(boolean logOnly) {
+ mLogOnlyMode = logOnly;
+ }
+
+ /**
+ * Execute this test run
+ *
+ * @param listener - listener to report results to
+ */
+ public void run(ITestRunListener listener) {
+ final String runCaseCommandStr = "am instrument -w -r "
+ + getClassCmd() + " " + getLogCmd() + " " + getExtraArgs() + " " + getRunnerPath();
+ Log.d(LOG_TAG, runCaseCommandStr);
+ mParser = new InstrumentationResultParser(listener);
+
+ try {
+ mRemoteDevice.executeShellCommand(runCaseCommandStr, mParser);
+ } catch (IOException e) {
+ Log.e(LOG_TAG, e);
+ listener.testRunFailed(e.toString());
+ }
+ }
+
+ /**
+ * Requests cancellation of this test run
+ */
+ public void cancel() {
+ if (mParser != null) {
+ mParser.cancel();
+ }
+ }
+
+ /**
+ * Returns the test class argument
+ */
+ private String getClassArg() {
+ return mClassArg;
+ }
+
+ /**
+ * Returns the full instrumentation command which specifies the test classes to execute.
+ * Returns an empty string if no classes were specified
+ */
+ private String getClassCmd() {
+ String classArg = getClassArg();
+ if (classArg != null) {
+ return "-e class " + classArg;
+ }
+ return "";
+ }
+
+ /**
+ * Returns the full command to enable log only mode - if specified. Otherwise returns an
+ * empty string
+ */
+ private String getLogCmd() {
+ if (mLogOnlyMode) {
+ return "-e log true";
+ }
+ else {
+ return "";
+ }
+ }
+}
diff --git a/tools/ddms/libs/ddmlib/tests/src/com/android/ddmlib/testrunner/InstrumentationResultParserTest.java b/tools/ddms/libs/ddmlib/tests/src/com/android/ddmlib/testrunner/InstrumentationResultParserTest.java
new file mode 100644
index 0000000..67f6198
--- /dev/null
+++ b/tools/ddms/libs/ddmlib/tests/src/com/android/ddmlib/testrunner/InstrumentationResultParserTest.java
@@ -0,0 +1,246 @@
+/*
+ * 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.ddmlib.testrunner;
+
+import junit.framework.TestCase;
+
+
+/**
+ * Tests InstrumentationResultParser
+ */
+public class InstrumentationResultParserTest extends TestCase {
+
+ private InstrumentationResultParser mParser;
+ private VerifyingTestResult mTestResult;
+
+ // static dummy test names to use for validation
+ private static final String CLASS_NAME = "com.test.FooTest";
+ private static final String TEST_NAME = "testFoo";
+ private static final String STACK_TRACE = "java.lang.AssertionFailedException";
+
+ /**
+ * @param name - test name
+ */
+ public InstrumentationResultParserTest(String name) {
+ super(name);
+ }
+
+ /**
+ * @see junit.framework.TestCase#setUp()
+ */
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mTestResult = new VerifyingTestResult();
+ mParser = new InstrumentationResultParser(mTestResult);
+ }
+
+ /**
+ * Tests that the test run started and test start events is sent on first
+ * bundle received
+ */
+ public void testTestStarted() {
+ StringBuilder output = buildCommonResult();
+ addStartCode(output);
+
+ injectTestString(output.toString());
+ assertCommonAttributes();
+ assertEquals(0, mTestResult.mNumTestsRun);
+ }
+
+ /**
+ * Tests that a single successful test execution
+ */
+ public void testTestSuccess() {
+ StringBuilder output = buildCommonResult();
+ addStartCode(output);
+ addCommonStatus(output);
+ addSuccessCode(output);
+
+ injectTestString(output.toString());
+ assertCommonAttributes();
+ assertEquals(1, mTestResult.mNumTestsRun);
+ assertEquals(0, mTestResult.mTestStatus);
+ }
+
+ /**
+ * Test basic parsing of failed test case
+ */
+ public void testTestFailed() {
+ StringBuilder output = buildCommonResult();
+ addStartCode(output);
+ addCommonStatus(output);
+ addStackTrace(output);
+ addFailureCode(output);
+
+ injectTestString(output.toString());
+ assertCommonAttributes();
+
+ assertEquals(1, mTestResult.mNumTestsRun);
+ assertEquals(ITestRunListener.STATUS_FAILURE, mTestResult.mTestStatus);
+ assertEquals(STACK_TRACE, mTestResult.mTrace);
+ }
+
+ /**
+ * Test basic parsing and conversion of time from output
+ */
+ public void testTimeParsing() {
+ final String timeString = "Time: 4.9";
+ injectTestString(timeString);
+ assertEquals(4900, mTestResult.mTestTime);
+ }
+
+ /**
+ * builds a common test result using TEST_NAME and TEST_CLASS
+ */
+ private StringBuilder buildCommonResult() {
+ StringBuilder output = new StringBuilder();
+ // add test start bundle
+ addCommonStatus(output);
+ addStatusCode(output, "1");
+ // add end test bundle, without status
+ addCommonStatus(output);
+ return output;
+ }
+
+ /**
+ * Adds common status results to the provided output
+ */
+ private void addCommonStatus(StringBuilder output) {
+ addStatusKey(output, "stream", "\r\n" + CLASS_NAME);
+ addStatusKey(output, "test", TEST_NAME);
+ addStatusKey(output, "class", CLASS_NAME);
+ addStatusKey(output, "current", "1");
+ addStatusKey(output, "numtests", "1");
+ addStatusKey(output, "id", "InstrumentationTestRunner");
+ }
+
+ /**
+ * Adds a stack trace status bundle to output
+ */
+ private void addStackTrace(StringBuilder output) {
+ addStatusKey(output, "stack", STACK_TRACE);
+
+ }
+
+ /**
+ * Helper method to add a status key-value bundle
+ */
+ private void addStatusKey(StringBuilder outputBuilder, String key,
+ String value) {
+ outputBuilder.append("INSTRUMENTATION_STATUS: ");
+ outputBuilder.append(key);
+ outputBuilder.append('=');
+ outputBuilder.append(value);
+ outputBuilder.append("\r\n");
+ }
+
+ private void addStartCode(StringBuilder outputBuilder) {
+ addStatusCode(outputBuilder, "1");
+ }
+
+ private void addSuccessCode(StringBuilder outputBuilder) {
+ addStatusCode(outputBuilder, "0");
+ }
+
+ private void addFailureCode(StringBuilder outputBuilder) {
+ addStatusCode(outputBuilder, "-2");
+ }
+
+ private void addStatusCode(StringBuilder outputBuilder, String value) {
+ outputBuilder.append("INSTRUMENTATION_STATUS_CODE: ");
+ outputBuilder.append(value);
+ outputBuilder.append("\r\n");
+ }
+
+ /**
+ * inject a test string into the result parser
+ *
+ * @param result
+ */
+ private void injectTestString(String result) {
+ byte[] data = result.getBytes();
+ mParser.addOutput(data, 0, data.length);
+ mParser.flush();
+ }
+
+ private void assertCommonAttributes() {
+ assertEquals(CLASS_NAME, mTestResult.mSuiteName);
+ assertEquals(1, mTestResult.mTestCount);
+ assertEquals(TEST_NAME, mTestResult.mTestName);
+ }
+
+ /**
+ * A specialized test listener that stores a single test events
+ */
+ private class VerifyingTestResult implements ITestRunListener {
+
+ String mSuiteName;
+ int mTestCount;
+ int mNumTestsRun;
+ String mTestName;
+ long mTestTime;
+ int mTestStatus;
+ String mTrace;
+ boolean mStopped;
+
+ VerifyingTestResult() {
+ mNumTestsRun = 0;
+ mTestStatus = 0;
+ mStopped = false;
+ }
+
+ public void testEnded(String className, String testName) {
+ mNumTestsRun++;
+ assertEquals("Unexpected class name", mSuiteName, className);
+ assertEquals("Unexpected test ended", mTestName, testName);
+
+ }
+
+ public void testFailed(int status, String className, String testName,
+ String trace) {
+ mTestStatus = status;
+ mTrace = trace;
+ assertEquals("Unexpected class name", mSuiteName, className);
+ assertEquals("Unexpected test ended", mTestName, testName);
+ }
+
+ public void testRunEnded(long elapsedTime) {
+ mTestTime = elapsedTime;
+
+ }
+
+ public void testRunStarted(int testCount) {
+ mTestCount = testCount;
+ }
+
+ public void testRunStopped(long elapsedTime) {
+ mTestTime = elapsedTime;
+ mStopped = true;
+ }
+
+ public void testStarted(String className, String testName) {
+ mSuiteName = className;
+ mTestName = testName;
+ }
+
+ public void testRunFailed(String errorMessage) {
+ // ignored
+ }
+ }
+
+}
diff --git a/tools/ddms/libs/ddmlib/tests/src/com/android/ddmlib/testrunner/RemoteAndroidTestRunnerTest.java b/tools/ddms/libs/ddmlib/tests/src/com/android/ddmlib/testrunner/RemoteAndroidTestRunnerTest.java
new file mode 100644
index 0000000..cd4aa26
--- /dev/null
+++ b/tools/ddms/libs/ddmlib/tests/src/com/android/ddmlib/testrunner/RemoteAndroidTestRunnerTest.java
@@ -0,0 +1,240 @@
+/*
+ * 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.ddmlib.testrunner;
+
+import com.android.ddmlib.Client;
+import com.android.ddmlib.FileListingService;
+import com.android.ddmlib.IDevice;
+import com.android.ddmlib.IShellOutputReceiver;
+import com.android.ddmlib.RawImage;
+import com.android.ddmlib.SyncService;
+import com.android.ddmlib.Device.DeviceState;
+import com.android.ddmlib.log.LogReceiver;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * Test RemoteAndroidTestRunner.
+ */
+public class RemoteAndroidTestRunnerTest extends TestCase {
+
+ private RemoteAndroidTestRunner mRunner;
+ private MockDevice mMockDevice;
+
+ private static final String TEST_PACKAGE = "com.test";
+ private static final String TEST_RUNNER = "com.test.InstrumentationTestRunner";
+
+ /**
+ * @see junit.framework.TestCase#setUp()
+ */
+ @Override
+ protected void setUp() throws Exception {
+ mMockDevice = new MockDevice();
+ mRunner = new RemoteAndroidTestRunner(TEST_PACKAGE, TEST_RUNNER, mMockDevice);
+ }
+
+ /**
+ * Test the basic case building of the instrumentation runner command with no arguments
+ */
+ public void testRun() {
+ mRunner.run(new EmptyListener());
+ assertStringsEquals(String.format("am instrument -w -r %s/%s", TEST_PACKAGE, TEST_RUNNER),
+ mMockDevice.getLastShellCommand());
+ }
+
+ /**
+ * Test the building of the instrumentation runner command with log set
+ */
+ public void testRunWithLog() {
+ mRunner.setLogOnly(true);
+ mRunner.run(new EmptyListener());
+ assertStringsEquals(String.format("am instrument -w -r -e log true %s/%s", TEST_PACKAGE,
+ TEST_RUNNER), mMockDevice.getLastShellCommand());
+ }
+
+ /**
+ * Test the building of the instrumentation runner command with method set
+ */
+ public void testRunWithMethod() {
+ final String className = "FooTest";
+ final String testName = "fooTest";
+ mRunner.setMethodName(className, testName);
+ mRunner.run(new EmptyListener());
+ assertStringsEquals(String.format("am instrument -w -r -e class %s#%s %s/%s", className,
+ testName, TEST_PACKAGE, TEST_RUNNER), mMockDevice.getLastShellCommand());
+ }
+
+ /**
+ * Test the building of the instrumentation runner command with extra args set
+ */
+ public void testRunWithExtraArgs() {
+ final String extraArgs = "blah";
+ mRunner.setExtraArgs(extraArgs);
+ mRunner.run(new EmptyListener());
+ assertStringsEquals(String.format("am instrument -w -r %s %s/%s", extraArgs,
+ TEST_PACKAGE, TEST_RUNNER), mMockDevice.getLastShellCommand());
+ }
+
+
+ /**
+ * Assert two strings are equal ignoring whitespace
+ */
+ private void assertStringsEquals(String str1, String str2) {
+ String strippedStr1 = str1.replaceAll(" ", "");
+ String strippedStr2 = str2.replaceAll(" ", "");
+ assertEquals(strippedStr1, strippedStr2);
+ }
+
+ /**
+ * A dummy device that does nothing except store the provided executed shell command for
+ * later retrieval
+ */
+ private static class MockDevice implements IDevice {
+
+ private String mLastShellCommand;
+
+ /**
+ * Stores the provided command for later retrieval from getLastShellCommand
+ */
+ public void executeShellCommand(String command,
+ IShellOutputReceiver receiver) throws IOException {
+ mLastShellCommand = command;
+ }
+
+ /**
+ * Get the last command provided to executeShellCommand
+ */
+ public String getLastShellCommand() {
+ return mLastShellCommand;
+ }
+
+ public boolean createForward(int localPort, int remotePort) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Client getClient(String applicationName) {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getClientName(int pid) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Client[] getClients() {
+ throw new UnsupportedOperationException();
+ }
+
+ public FileListingService getFileListingService() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Map<String, String> getProperties() {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getProperty(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public int getPropertyCount() {
+ throw new UnsupportedOperationException();
+ }
+
+ public RawImage getScreenshot() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getSerialNumber() {
+ throw new UnsupportedOperationException();
+ }
+
+ public DeviceState getState() {
+ throw new UnsupportedOperationException();
+ }
+
+ public SyncService getSyncService() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean hasClients() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isBootLoader() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isEmulator() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isOffline() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isOnline() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean removeForward(int localPort, int remotePort) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void runEventLogService(LogReceiver receiver) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+
+ /** An empty implementation of TestRunListener
+ */
+ private static class EmptyListener implements ITestRunListener {
+
+ public void testEnded(String className, String testName) {
+ // ignore
+ }
+
+ public void testFailed(int status, String className, String testName,
+ String trace) {
+ // ignore
+ }
+
+ public void testRunEnded(long elapsedTime) {
+ // ignore
+ }
+
+ public void testRunFailed(String errorMessage) {
+ // ignore
+ }
+
+ public void testRunStarted(int testCount) {
+ // ignore
+ }
+
+ public void testRunStopped(long elapsedTime) {
+ // ignore
+ }
+
+ public void testStarted(String className, String testName) {
+ // ignore
+ }
+
+ }
+}
diff --git a/tools/ddms/libs/ddmuilib/README b/tools/ddms/libs/ddmuilib/README
index 36a45c6..d66b84a 100644
--- a/tools/ddms/libs/ddmuilib/README
+++ b/tools/ddms/libs/ddmuilib/README
@@ -2,10 +2,10 @@
ddmuilib requires SWT to compile.
-SWT is available in the depot under //device/prebuild/<platform>/swt
+SWT is available in the depot under prebuild/<platform>/swt
Because the build path cannot contain relative path that are not inside the project directory,
the .classpath file references a user library called ANDROID_SWT.
In order to compile the project, make a user library called ANDROID_SWT containing the jar
-available at //device/prebuild/<platform>/swt.
\ No newline at end of file
+available at prebuild/<platform>/swt.
\ No newline at end of file
diff --git a/tools/ddms/libs/ddmuilib/src/com/android/ddmuilib/SysinfoPanel.java b/tools/ddms/libs/ddmuilib/src/com/android/ddmuilib/SysinfoPanel.java
index 1f937a3..8ef237c 100644
--- a/tools/ddms/libs/ddmuilib/src/com/android/ddmuilib/SysinfoPanel.java
+++ b/tools/ddms/libs/ddmuilib/src/com/android/ddmuilib/SysinfoPanel.java
@@ -323,6 +323,39 @@
}
/**
+ * Parse the time string generated by BatteryStats.
+ * A typical new-format string is "11d 13h 45m 39s 999ms".
+ * A typical old-format string is "12.3 sec".
+ * @return time in ms
+ */
+ private static long parseTimeMs(String s) {
+ long total = 0;
+ // Matches a single component e.g. "12.3 sec" or "45ms"
+ Pattern p = Pattern.compile("([\\d\\.]+)\\s*([a-z]+)");
+ Matcher m = p.matcher(s);
+ while (m.find()) {
+ String label = m.group(2);
+ if ("sec".equals(label)) {
+ // Backwards compatibility with old time format
+ total += (long) (Double.parseDouble(m.group(1)) * 1000);
+ continue;
+ }
+ long value = Integer.parseInt(m.group(1));
+ if ("d".equals(label)) {
+ total += value * 24 * 60 * 60 * 1000;
+ } else if ("h".equals(label)) {
+ total += value * 60 * 60 * 1000;
+ } else if ("m".equals(label)) {
+ total += value * 60 * 1000;
+ } else if ("s".equals(label)) {
+ total += value * 1000;
+ } else if ("ms".equals(label)) {
+ total += value;
+ }
+ }
+ return total;
+ }
+ /**
* Processes wakelock information from bugreport. Updates mDataset with the
* new data.
*
@@ -330,8 +363,8 @@
* @throws IOException if error reading file
*/
void readWakelockDataset(BufferedReader br) throws IOException {
- Pattern lockPattern = Pattern.compile("Wake lock (\\S+): (\\S+) sec");
- Pattern totalPattern = Pattern.compile("Total: (\\S+)");
+ Pattern lockPattern = Pattern.compile("Wake lock (\\S+): (.+) partial");
+ Pattern totalPattern = Pattern.compile("Total: (.+) uptime");
double total = 0;
boolean inCurrent = false;
@@ -346,13 +379,14 @@
} else if (inCurrent) {
Matcher m = lockPattern.matcher(line);
if (m.find()) {
- double value = Double.parseDouble(m.group(2));
+ double value = parseTimeMs(m.group(2)) / 1000.;
mDataset.setValue(m.group(1), value);
total -= value;
- }
- m = totalPattern.matcher(line);
- if (m.find()) {
- total += Double.parseDouble(m.group(1));
+ } else {
+ m = totalPattern.matcher(line);
+ if (m.find()) {
+ total += parseTimeMs(m.group(1)) / 1000.;
+ }
}
}
}
diff --git a/tools/eclipse/buildConfig/allElements.xml b/tools/eclipse/buildConfig/allElements.xml
index 79f06df..99ab3aa 100644
--- a/tools/eclipse/buildConfig/allElements.xml
+++ b/tools/eclipse/buildConfig/allElements.xml
@@ -19,11 +19,6 @@
<property name="id" value="com.android.ide.eclipse.adt" />
</ant>
- <ant antfile="${genericTargets}" target="${target}">
- <property name="type" value="feature" />
- <property name="id" value="com.android.ide.eclipse.editors" />
- </ant>
-
<antcall target="buildInternalFeatures"/>
</target>
@@ -35,15 +30,10 @@
<target name="buildInternalFeatures" if="internalSite">
<ant antfile="${genericTargets}" target="${target}">
<property name="type" value="feature" />
- <property name="id" value="com.android.ide.eclipse.platform" />
- </ant>
- <ant antfile="${genericTargets}" target="${target}">
- <property name="type" value="feature" />
<property name="id" value="com.android.ide.eclipse.tests" />
</ant>
</target>
-
<!-- ===================================================================== -->
<!-- Targets to assemble the built elements for particular configurations -->
<!-- These generally call the generated assemble scripts (named in -->
@@ -55,14 +45,6 @@
<ant antfile="${assembleScriptName}" dir="${buildDirectory}"/>
</target>
- <target name="assemble.com.android.ide.eclipse.editors">
- <ant antfile="${assembleScriptName}" dir="${buildDirectory}"/>
- </target>
-
- <target name="assemble.com.android.ide.eclipse.platform">
- <ant antfile="${assembleScriptName}" dir="${buildDirectory}"/>
- </target>
-
<target name="assemble.com.android.ide.eclipse.tests">
<ant antfile="${assembleScriptName}" dir="${buildDirectory}"/>
</target>
diff --git a/tools/eclipse/changes.txt b/tools/eclipse/changes.txt
index bbe26de..5cb8245 100644
--- a/tools/eclipse/changes.txt
+++ b/tools/eclipse/changes.txt
@@ -1,3 +1,6 @@
+0.9.0 (work in progress)
+- Support for SDK with multiple versions of the Android platform and vendor supplied add-ons.
+
0.8.1:
- Alternate Layout wizard. In the layout editor, the "create" button is now enabled, and allows to easily create alternate versions.
@@ -5,6 +8,8 @@
- Export Wizard: To export an application for release, sign with a non debug key. Accessible from the export menu, from the Android Tools contextual menu, or from the overview page of the manifest editor.
- New XML File Wizard: To easily create new XML resources file in the /res directory.
- New checks on launch when attempting to debug on a device.
+- Basic support for drag'n'drop in Graphical layout editor. You can add new items by drag'n'drop from the palette. There's is no support for moving/resizing yet.
+- Undo/redo support in all XML form editors and Graphical layout editor.
0.8.0:
diff --git a/tools/eclipse/features/com.android.ide.eclipse.adt/feature.xml b/tools/eclipse/features/com.android.ide.eclipse.adt/feature.xml
index f8356b0..191b76d 100644
--- a/tools/eclipse/features/com.android.ide.eclipse.adt/feature.xml
+++ b/tools/eclipse/features/com.android.ide.eclipse.adt/feature.xml
@@ -2,7 +2,7 @@
<feature
id="com.android.ide.eclipse.adt"
label="Android Development Tools"
- version="0.8.1.qualifier"
+ version="0.9.0.qualifier"
provider-name="The Android Open Source Project"
plugin="com.android.ide.eclipse.adt">
@@ -14,37 +14,35 @@
Copyright (C) 2007 The Android Open Source Project
</copyright>
+ <license>
+ License TBD.
+ </license>
+
<url>
<update label="Android Update Site" url="https://dl-ssl.google.com/android/eclipse/"/>
</url>
<requires>
- <import plugin="org.eclipse.core.resources"/>
<import plugin="org.eclipse.core.runtime"/>
- <import plugin="org.eclipse.jdt.core"/>
- <import plugin="org.eclipse.ui.console"/>
- <import plugin="org.eclipse.ui"/>
- <import plugin="org.eclipse.jdt.ui"/>
- <import plugin="org.eclipse.jface.text"/>
- <import plugin="org.eclipse.ui.editors"/>
+ <import plugin="org.eclipse.core.resources"/>
<import plugin="org.eclipse.debug.core"/>
<import plugin="org.eclipse.debug.ui"/>
<import plugin="org.eclipse.jdt"/>
<import plugin="org.eclipse.ant.core"/>
+ <import plugin="org.eclipse.jdt.core"/>
+ <import plugin="org.eclipse.jdt.ui"/>
<import plugin="org.eclipse.jdt.launching"/>
+ <import plugin="org.eclipse.jface.text"/>
+ <import plugin="org.eclipse.ui.editors"/>
<import plugin="org.eclipse.ui.workbench.texteditor"/>
+ <import plugin="org.eclipse.ui.console"/>
<import plugin="org.eclipse.core.filesystem"/>
+ <import plugin="org.eclipse.ui"/>
<import plugin="org.eclipse.ui.ide"/>
+ <import plugin="org.eclipse.ui.forms"/>
</requires>
<plugin
- id="com.android.ide.eclipse.common"
- download-size="0"
- install-size="0"
- version="0.0.0"
- unpack="false"/>
-
- <plugin
id="com.android.ide.eclipse.adt"
download-size="0"
install-size="0"
diff --git a/tools/eclipse/features/com.android.ide.eclipse.editors/build.properties b/tools/eclipse/features/com.android.ide.eclipse.editors/build.properties
deleted file mode 100644
index 64f93a9..0000000
--- a/tools/eclipse/features/com.android.ide.eclipse.editors/build.properties
+++ /dev/null
@@ -1 +0,0 @@
-bin.includes = feature.xml
diff --git a/tools/eclipse/features/com.android.ide.eclipse.editors/feature.xml b/tools/eclipse/features/com.android.ide.eclipse.editors/feature.xml
deleted file mode 100644
index f5f92e8..0000000
--- a/tools/eclipse/features/com.android.ide.eclipse.editors/feature.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<feature
- id="com.android.ide.eclipse.editors"
- label="Android Editors"
- version="0.8.1.qualifier"
- provider-name="The Android Open Source Project"
- plugin="com.android.ide.eclipse.editors">
-
- <description>
- This feature provides Editors for Android files.
- </description>
-
- <copyright>
- Copyright (C) 2007 The Android Open Source Project
- </copyright>
-
- <url>
- <update label="Android Update Site" url="https://dl-ssl.google.com/android/eclipse/"/>
- </url>
-
- <requires>
- <import plugin="com.android.ide.eclipse.common"/>
- <import plugin="org.eclipse.ui"/>
- <import plugin="org.eclipse.core.runtime"/>
- <import plugin="org.eclipse.core.resources"/>
- <import plugin="org.eclipse.ui.editors"/>
- <import plugin="org.eclipse.jface.text"/>
- <import plugin="org.eclipse.ui.ide"/>
- <import plugin="org.eclipse.wst.sse.ui"/>
- <import plugin="org.eclipse.wst.xml.ui"/>
- <import plugin="org.eclipse.wst.xml.core"/>
- <import plugin="org.eclipse.wst.sse.core"/>
- <import plugin="org.eclipse.ui.forms"/>
- <import plugin="org.eclipse.jdt.core"/>
- <import plugin="org.eclipse.ui.browser"/>
- <import plugin="org.eclipse.jdt.ui"/>
- <import plugin="org.eclipse.gef"/>
- <import plugin="org.eclipse.ui.views"/>
- <import plugin="org.eclipse.ui.console"/>
- </requires>
-
- <plugin
- id="com.android.ide.eclipse.editors"
- download-size="0"
- install-size="0"
- version="0.0.0"
- unpack="false"/>
-
-</feature>
diff --git a/tools/eclipse/features/com.android.ide.eclipse.platform/.project b/tools/eclipse/features/com.android.ide.eclipse.platform/.project
deleted file mode 100644
index 0bb8c34..0000000
--- a/tools/eclipse/features/com.android.ide.eclipse.platform/.project
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>platform-feature</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.pde.FeatureBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.pde.FeatureNature</nature>
- </natures>
-</projectDescription>
diff --git a/tools/eclipse/features/com.android.ide.eclipse.platform/build.properties b/tools/eclipse/features/com.android.ide.eclipse.platform/build.properties
deleted file mode 100644
index 64f93a9..0000000
--- a/tools/eclipse/features/com.android.ide.eclipse.platform/build.properties
+++ /dev/null
@@ -1 +0,0 @@
-bin.includes = feature.xml
diff --git a/tools/eclipse/features/com.android.ide.eclipse.platform/feature.xml b/tools/eclipse/features/com.android.ide.eclipse.platform/feature.xml
deleted file mode 100644
index aa4b166..0000000
--- a/tools/eclipse/features/com.android.ide.eclipse.platform/feature.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<feature
- id="com.android.ide.eclipse.platform"
- label="Android Platform Tools"
- version="0.8.1.qualifier"
- provider-name="The Android Open Source Project">
-
- <description>
- This feature provides a ddms perspective and editor functionnality for Android.
- </description>
-
- <copyright>
- Copyright (C) 2007 The Android Open Source Project
- </copyright>
-
- <url>
- <update label="Android Update Site" url="https://android.corp.google.com/adt/"/>
- </url>
-
- <requires>
- <import plugin="org.eclipse.core.resources"/>
- <import plugin="org.eclipse.core.runtime"/>
- <import plugin="org.eclipse.jdt.core"/>
- <import plugin="org.eclipse.ui.console"/>
- <import plugin="org.eclipse.ui"/>
- <import plugin="org.eclipse.jdt.ui"/>
- <import plugin="org.eclipse.jface.text"/>
- <import plugin="org.eclipse.ui.editors"/>
- </requires>
-
- <plugin
- id="com.android.ide.eclipse.common"
- download-size="0"
- install-size="0"
- version="0.0.0"
- unpack="false"/>
-
- <plugin
- id="com.android.ide.eclipse.platform"
- download-size="0"
- install-size="0"
- version="0.0.0"
- unpack="false"/>
-
- <plugin
- id="com.android.ide.eclipse.ddms"
- download-size="0"
- install-size="0"
- version="0.0.0"
- unpack="false"/>
-
-</feature>
diff --git a/tools/eclipse/features/com.android.ide.eclipse.tests/feature.xml b/tools/eclipse/features/com.android.ide.eclipse.tests/feature.xml
index b5a848c..2a3a74f 100644
--- a/tools/eclipse/features/com.android.ide.eclipse.tests/feature.xml
+++ b/tools/eclipse/features/com.android.ide.eclipse.tests/feature.xml
@@ -2,11 +2,11 @@
<feature
id="com.android.ide.eclipse.tests"
label="ADT Tests"
- version="0.8.1.qualifier"
+ version="0.9.0.qualifier"
provider-name="The Android Open Source Project">
- <copyright>
- Copyright (C) 2007 The Android Open Source Project
+ <copyright>
+ Copyright (C) 2007 The Android Open Source Project
</copyright>
<requires>
@@ -15,8 +15,6 @@
<import plugin="org.eclipse.core.resources"/>
<import plugin="com.android.ide.eclipse.adt"/>
<import plugin="org.junit"/>
- <import plugin="com.android.ide.eclipse.common"/>
- <import plugin="com.android.ide.eclipse.editors"/>
<import plugin="org.eclipse.jdt.core"/>
<import plugin="org.eclipse.jdt.launching"/>
<import plugin="org.eclipse.ui.views"/>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/.classpath b/tools/eclipse/plugins/com.android.ide.eclipse.adt/.classpath
index 4dd4cac..bbcdff9 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/.classpath
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/.classpath
@@ -5,5 +5,12 @@
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="lib" path="jarutils.jar"/>
<classpathentry kind="lib" path="androidprefs.jar"/>
+ <classpathentry kind="lib" path="sdkstats.jar"/>
+ <classpathentry kind="lib" path="kxml2-2.3.0.jar"/>
+ <classpathentry kind="lib" path="layoutlib_api.jar"/>
+ <classpathentry kind="lib" path="layoutlib_utils.jar"/>
+ <classpathentry kind="lib" path="ninepatch.jar"/>
+ <classpathentry kind="lib" path="sdklib.jar"/>
+ <classpathentry kind="lib" path="sdkuilib.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF b/tools/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
index 9926074..a464d5c 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
@@ -2,14 +2,20 @@
Bundle-ManifestVersion: 2
Bundle-Name: Android Development Toolkit
Bundle-SymbolicName: com.android.ide.eclipse.adt;singleton:=true
-Bundle-Version: 0.8.1.qualifier
+Bundle-Version: 0.9.0.qualifier
Bundle-ClassPath: .,
jarutils.jar,
- androidprefs.jar
+ androidprefs.jar,
+ sdkstats.jar,
+ kxml2-2.3.0.jar,
+ layoutlib_api.jar,
+ ninepatch.jar,
+ layoutlib_utils.jar,
+ sdklib.jar,
+ sdkuilib.jar
Bundle-Activator: com.android.ide.eclipse.adt.AdtPlugin
Bundle-Vendor: The Android Open Source Project
-Require-Bundle: com.android.ide.eclipse.common,
- com.android.ide.eclipse.ddms,
+Require-Bundle: com.android.ide.eclipse.ddms,
org.eclipse.core.runtime,
org.eclipse.core.resources,
org.eclipse.debug.core,
@@ -26,11 +32,48 @@
org.eclipse.core.filesystem,
org.eclipse.ui,
org.eclipse.ui.ide,
- org.eclipse.ui.forms
+ org.eclipse.ui.forms,
+ org.eclipse.gef,
+ org.eclipse.ui.browser,
+ org.eclipse.ui.views,
+ org.eclipse.wst.sse.core,
+ org.eclipse.wst.sse.ui,
+ org.eclipse.wst.xml.core,
+ org.eclipse.wst.xml.ui
Eclipse-LazyStart: true
-Export-Package: com.android.ide.eclipse.adt.build;x-friends:="com.android.ide.eclipse.tests",
+Export-Package: com.android.ide.eclipse.adt,
+ com.android.ide.eclipse.adt.build;x-friends:="com.android.ide.eclipse.tests",
com.android.ide.eclipse.adt.project;x-friends:="com.android.ide.eclipse.tests",
com.android.ide.eclipse.adt.project.internal;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.adt.resources;x-friends:="com.android.ide.eclipse.tests"
+ com.android.ide.eclipse.adt.sdk;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.adt.wizards.newproject;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.common,
+ com.android.ide.eclipse.common.project,
+ com.android.ide.eclipse.common.resources,
+ com.android.ide.eclipse.editors;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.descriptors;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.layout;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.layout.descriptors;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.layout.parts;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.layout.uimodel;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.manifest;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.manifest.descriptors;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.manifest.model;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.manifest.pages;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.menu;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.menu.descriptors;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.resources;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.resources.configurations;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.resources.descriptors;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.resources.explorer;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.resources.manager;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.resources.manager.files;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.resources.uimodel;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.ui;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.ui.tree;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.uimodel;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.wizards;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.xml;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.xml.descriptors;x-friends:="com.android.ide.eclipse.tests"
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/build.properties b/tools/eclipse/plugins/com.android.ide.eclipse.adt/build.properties
index 6d6c2e8..c7eb749 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/build.properties
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/build.properties
@@ -5,6 +5,13 @@
templates/,\
about.ini,\
jarutils.jar,\
- androidprefs.jar
+ androidprefs.jar,\
+ sdkstats.jar,\
+ kxml2-2.3.0.jar,\
+ layoutlib_api.jar,\
+ layoutlib_utils.jar,\
+ ninepatch.jar,\
+ sdklib.jar,\
+ sdkuilib.jar
source.. = src/
output.. = bin/
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/add.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/add.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/add.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/add.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/az_sort.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/az_sort.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/az_sort.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/az_sort.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/delete.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/delete.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/delete.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/delete.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/dimension.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/dimension.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/dimension.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/dimension.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/down.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/down.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/down.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/down.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/dpi.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/dpi.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/dpi.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/dpi.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/error.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/error.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/error.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/error.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/keyboard.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/keyboard.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/keyboard.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/keyboard.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/language.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/language.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/language.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/language.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/match.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/match.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/match.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/match.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/mcc.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/mcc.png
new file mode 100644
index 0000000..4dc95d7
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/mcc.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/mnc.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/mnc.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/mnc.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/mnc.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/navpad.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/navpad.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/navpad.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/navpad.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/orientation.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/orientation.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/orientation.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/orientation.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/region.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/region.png
new file mode 100644
index 0000000..9608cd6
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/region.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/text_input.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/text_input.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/text_input.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/text_input.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/touch.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/touch.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/touch.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/touch.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/up.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/up.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/up.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/up.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/warning.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/warning.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/warning.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/warning.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml b/tools/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
index 51b1291..ade4646 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
@@ -2,6 +2,38 @@
<?eclipse version="3.2"?>
<plugin>
<extension
+ id="com.android.ide.eclipse.common.xmlProblem"
+ name="Android XML Format Problem"
+ point="org.eclipse.core.resources.markers">
+ <super type="org.eclipse.core.resources.problemmarker"/>
+ <super type="org.eclipse.core.resources.textmarker"/>
+ <persistent value="true"/>
+ </extension>
+ <extension
+ id="com.android.ide.eclipse.common.aaptProblem"
+ name="Android AAPT Problem"
+ point="org.eclipse.core.resources.markers">
+ <super type="org.eclipse.core.resources.problemmarker"/>
+ <super type="org.eclipse.core.resources.textmarker"/>
+ <persistent value="true"/>
+ </extension>
+ <extension
+ id="com.android.ide.eclipse.common.aidlProblem"
+ name="Android AIDL Problem"
+ point="org.eclipse.core.resources.markers">
+ <super type="org.eclipse.core.resources.problemmarker"/>
+ <super type="org.eclipse.core.resources.textmarker"/>
+ <persistent value="true"/>
+ </extension>
+ <extension
+ id="com.android.ide.eclipse.common.androidProblem"
+ name="Android XML Content Problem"
+ point="org.eclipse.core.resources.markers">
+ <super type="org.eclipse.core.resources.problemmarker"/>
+ <super type="org.eclipse.core.resources.textmarker"/>
+ <persistent value="true"/>
+ </extension>
+ <extension
id="ResourceManagerBuilder"
name="Android Resource Manager"
point="org.eclipse.core.resources.builders">
@@ -47,7 +79,7 @@
<wizard
canFinishEarly="false"
category="com.android.ide.eclipse.wizards.category"
- class="com.android.ide.eclipse.adt.project.internal.NewProjectWizard"
+ class="com.android.ide.eclipse.adt.wizards.newproject.NewProjectWizard"
finalPerspective="org.eclipse.jdt.ui.JavaPerspective"
hasPages="true"
icon="icons/android.png"
@@ -55,6 +87,18 @@
name="Android Project"
preferredPerspectives="org.eclipse.jdt.ui.JavaPerspective"
project="true"/>
+ <wizard
+ canFinishEarly="false"
+ category="com.android.ide.eclipse.wizards.category"
+ class="com.android.ide.eclipse.editors.wizards.NewXmlFileWizard"
+ finalPerspective="org.eclipse.jdt.ui.JavaPerspective"
+ hasPages="true"
+ icon="icons/android.png"
+ id="com.android.ide.eclipse.editors.wizards.NewXmlFileWizard"
+ name="Android XML File"
+ preferredPerspectives="org.eclipse.jdt.ui.JavaPerspective"
+ project="false">
+ </wizard>
</extension>
<extension
point="org.eclipse.debug.core.launchConfigurationTypes">
@@ -174,6 +218,13 @@
label="Create Aidl preprocess file for Parcelable classes"
menubarPath="com.android.ide.eclipse.adt.AndroidTools/group1"/>
<action
+ class="com.android.ide.eclipse.adt.project.NewXmlFileWizardAction"
+ enablesFor="1"
+ id="com.android.ide.eclipse.adt.project.NewXmlFileWizardAction"
+ label="New Resource File..."
+ menubarPath="com.android.ide.eclipse.adt.AndroidTools/group1">
+ </action>
+ <action
class="com.android.ide.eclipse.adt.project.ExportAction"
enablesFor="1"
id="com.android.ide.eclipse.adt.project.ExportAction"
@@ -183,7 +234,7 @@
class="com.android.ide.eclipse.adt.project.ExportWizardAction"
enablesFor="1"
id="com.android.ide.eclipse.adt.project.ExportWizardAction"
- label="Export Application..."
+ label="Export Signed Application Package..."
menubarPath="com.android.ide.eclipse.adt.AndroidTools/group2"/>
<action
class="com.android.ide.eclipse.adt.project.FixProjectAction"
@@ -209,30 +260,32 @@
class="com.android.ide.eclipse.adt.preferences.LaunchPreferencePage"
id="com.android.ide.eclipse.adt.preferences.LaunchPreferencePage"
name="Launch"/>
+ <page
+ category="com.android.ide.eclipse.preferences.main"
+ class="com.android.ide.eclipse.common.preferences.UsagePreferencePage"
+ id="com.android.ide.eclipse.common.preferences.UsagePreferencePage"
+ name="Usage Stats">
+ </page>
</extension>
<extension
point="org.eclipse.core.runtime.preferences">
<initializer class="com.android.ide.eclipse.adt.preferences.PreferenceInitializer"/>
</extension>
<extension
- point="org.eclipse.ui.editors">
- <editor
- class="com.android.ide.eclipse.adt.editors.java.ReadOnlyJavaEditor"
- contributorClass="org.eclipse.ui.texteditor.BasicTextEditorActionContributor"
- default="true"
- filenames="R.java, Manifest.java"
- icon="icons/android.png"
- id="com.android.ide.eclipse.adt.editors.java.ReadOnlyJavaEditor"
- name="Android Java Editor"/>
- </extension>
- <extension
id="com.android.ide.eclipse.adt.adtProblem"
- name="Generic ADT Problem"
+ name="Android ADT Problem"
point="org.eclipse.core.resources.markers">
<super type="org.eclipse.core.resources.problemmarker"/>
<persistent value="true"/>
</extension>
<extension
+ id="com.android.ide.eclipse.adt.targetProblem"
+ name="Android Target Problem"
+ point="org.eclipse.core.resources.markers">
+ <super type="org.eclipse.core.resources.problemmarker"/>
+ <persistent value="false"/>
+ </extension>
+ <extension
point="org.eclipse.ui.perspectiveExtensions">
<perspectiveExtension targetID="org.eclipse.jdt.ui.JavaPerspective">
<newWizardShortcut id="com.android.ide.eclipse.adt.project.NewProjectWizard" />
@@ -305,4 +358,110 @@
keyConfigurationId="org.eclipse.ui.defaultAcceleratorConfiguration">
</keyBinding>
</extension>
+ <extension
+ point="org.eclipse.ui.decorators">
+ <decorator
+ adaptable="true"
+ class="com.android.ide.eclipse.adt.project.FolderDecorator"
+ id="com.android.ide.eclipse.adt.project.FolderDecorator"
+ label="Android Decorator"
+ lightweight="true"
+ location="TOP_RIGHT"
+ objectClass="org.eclipse.core.resources.IFolder"
+ state="true">
+ </decorator>
+ </extension>
+ <extension
+ point="org.eclipse.ui.editors">
+ <editor
+ class="com.android.ide.eclipse.editors.manifest.ManifestEditor"
+ default="true"
+ filenames="AndroidManifest.xml"
+ icon="icons/android.png"
+ id="com.android.ide.eclipse.editors.manifest.ManifestEditor"
+ name="Android Manifest Editor">
+ </editor>
+ <editor
+ class="com.android.ide.eclipse.editors.resources.ResourcesEditor"
+ default="false"
+ extensions="xml"
+ icon="icons/android.png"
+ id="com.android.ide.eclipse.editors.resources.ResourcesEditor"
+ name="Android Resource Editor">
+ </editor>
+ <editor
+ class="com.android.ide.eclipse.editors.layout.LayoutEditor"
+ default="false"
+ extensions="xml"
+ icon="icons/android.png"
+ id="com.android.ide.eclipse.editors.layout.LayoutEditor"
+ matchingStrategy="com.android.ide.eclipse.editors.layout.MatchingStrategy"
+ name="Android Layout Editor">
+ </editor>
+ <editor
+ class="com.android.ide.eclipse.editors.menu.MenuEditor"
+ default="false"
+ extensions="xml"
+ icon="icons/android.png"
+ id="com.android.ide.eclipse.editors.menu.MenuEditor"
+ name="Android Menu Editor">
+ </editor>
+ <editor
+ class="com.android.ide.eclipse.editors.xml.XmlEditor"
+ default="false"
+ extensions="xml"
+ icon="icons/android.png"
+ id="com.android.ide.eclipse.editors.xml.XmlEditor"
+ name="Android Xml Resources Editor">
+ </editor>
+ </extension>
+ <extension
+ point="org.eclipse.ui.views">
+ <view
+ allowMultiple="false"
+ category="com.android.ide.eclipse.ddms.views.category"
+ class="com.android.ide.eclipse.editors.resources.explorer.ResourceExplorerView"
+ icon="icons/android.png"
+ id="com.android.ide.eclipse.editors.resources.explorer.ResourceExplorerView"
+ name="Resource Explorer">
+ </view>
+ </extension>
+ <extension
+ point="org.eclipse.wst.sse.ui.editorConfiguration">
+ <sourceViewerConfiguration
+ class="com.android.ide.eclipse.editors.manifest.ManifestSourceViewerConfig"
+ target="com.android.ide.eclipse.editors.manifest.ManifestEditor">
+ </sourceViewerConfiguration>
+ <sourceViewerConfiguration
+ class="com.android.ide.eclipse.editors.resources.ResourcesSourceViewerConfig"
+ target="com.android.ide.eclipse.editors.resources.ResourcesEditor">
+ </sourceViewerConfiguration>
+ <sourceViewerConfiguration
+ class="com.android.ide.eclipse.editors.layout.LayoutSourceViewerConfig"
+ target="com.android.ide.eclipse.editors.layout.LayoutEditor">
+ </sourceViewerConfiguration>
+ <sourceViewerConfiguration
+ class="com.android.ide.eclipse.editors.menu.MenuSourceViewerConfig"
+ target="com.android.ide.eclipse.editors.menu.MenuEditor">
+ </sourceViewerConfiguration>
+ <sourceViewerConfiguration
+ class="com.android.ide.eclipse.editors.xml.XmlSourceViewerConfig"
+ target="com.android.ide.eclipse.editors.xml.XmlEditor">
+ </sourceViewerConfiguration>
+ </extension>
+ <extension
+ point="org.eclipse.ui.propertyPages">
+ <page
+ adaptable="true"
+ class="com.android.ide.eclipse.adt.project.properties.AndroidPropertyPage"
+ id="com.android.ide.eclipse.adt.project.properties.AndroidPropertyPage"
+ name="Android"
+ nameFilter="*"
+ objectClass="org.eclipse.core.resources.IProject">
+ <enabledWhen>
+ <test property="org.eclipse.jdt.launching.hasProjectNature"
+ args="com.android.ide.eclipse.adt.AndroidNature"/>
+ </enabledWhen>
+ </page>
+ </extension>
</plugin>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java
index 6d52aa5..61b3f4d 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java
@@ -17,6 +17,7 @@
package com.android.ide.eclipse.adt;
+
/**
* Constant definition class.<br>
* <br>
@@ -39,6 +40,12 @@
/** Generic marker for ADT errors. */
public final static String MARKER_ADT = AdtPlugin.PLUGIN_ID + ".adtProblem"; //$NON-NLS-1$
+ /** Marker for Android Target errors.
+ * This is not cleared on each like other markers. Instead, it's cleared
+ * when a ContainerClasspathInitialized has succeeded in creating an
+ * {@link AndroidClasspathContainer}*/
+ public final static String MARKER_TARGET = AdtPlugin.PLUGIN_ID + ".targetProblem"; //$NON-NLS-1$
+
/** Build verbosity "Always". Those messages are always displayed. */
public final static int BUILD_ALWAYS = 0;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
index 9b24b07..d9c18cf 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
@@ -22,34 +22,55 @@
import com.android.ddmuilib.console.IDdmConsole;
import com.android.ide.eclipse.adt.build.DexWrapper;
import com.android.ide.eclipse.adt.debug.launching.AndroidLaunchController;
-import com.android.ide.eclipse.adt.debug.ui.SkinRepository;
import com.android.ide.eclipse.adt.preferences.BuildPreferencePage;
import com.android.ide.eclipse.adt.project.ProjectHelper;
import com.android.ide.eclipse.adt.project.export.ExportWizard;
import com.android.ide.eclipse.adt.project.internal.AndroidClasspathContainerInitializer;
-import com.android.ide.eclipse.adt.resources.FrameworkResourceParser;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetParser;
+import com.android.ide.eclipse.adt.sdk.LoadStatus;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.CommonPlugin;
import com.android.ide.eclipse.common.EclipseUiHelper;
import com.android.ide.eclipse.common.SdkStatsHelper;
import com.android.ide.eclipse.common.StreamHelper;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
import com.android.ide.eclipse.common.project.ExportHelper;
import com.android.ide.eclipse.common.project.ExportHelper.IExportCallback;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
import com.android.ide.eclipse.ddms.DdmsPlugin;
import com.android.ide.eclipse.ddms.ImageLoader;
+import com.android.ide.eclipse.editors.IconFactory;
+import com.android.ide.eclipse.editors.layout.LayoutEditor;
+import com.android.ide.eclipse.editors.menu.MenuEditor;
+import com.android.ide.eclipse.editors.resources.ResourcesEditor;
+import com.android.ide.eclipse.editors.resources.manager.ProjectResources;
+import com.android.ide.eclipse.editors.resources.manager.ResourceFolder;
+import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType;
+import com.android.ide.eclipse.editors.resources.manager.ResourceManager;
+import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor;
+import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IFileListener;
+import com.android.ide.eclipse.editors.xml.XmlEditor;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.SdkConstants;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
+import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
@@ -57,14 +78,21 @@
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorDescriptor;
+import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.console.ConsolePlugin;
+import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.IConsoleConstants;
import org.eclipse.ui.console.MessageConsole;
import org.eclipse.ui.console.MessageConsoleStream;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@@ -81,6 +109,8 @@
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
/**
* The activator class controls the plug-in life cycle
@@ -106,14 +136,17 @@
/** singleton instance */
private static AdtPlugin sPlugin;
+ private static Image sAndroidLogo;
+ private static ImageDescriptor sAndroidLogoDesc;
+
/** default store, provided by eclipse */
private IPreferenceStore mStore;
/** cached location for the sdk folder */
private String mOsSdkLocation;
- /** SDK Api Version */
- String mSdkApiVersion;
+ /** The global android console */
+ private MessageConsole mAndroidConsole;
/** Stream to write in the android console */
private MessageConsoleStream mAndroidConsoleStream;
@@ -130,14 +163,14 @@
/** Color used in the error console */
private Color mRed;
- private final ArrayList<IJavaProject> mPostDexProjects = new ArrayList<IJavaProject>();
+ /** Load status of the SDK. Any access MUST be in a synchronized(mPostLoadProjects) block */
+ private LoadStatus mSdkIsLoaded = LoadStatus.LOADING;
+ /** Project to update once the SDK is loaded.
+ * Any access MUST be in a synchronized(mPostLoadProjects) block */
+ private final ArrayList<IJavaProject> mPostLoadProjects = new ArrayList<IJavaProject>();
- /** Boolean wrapper to run dialog in the UI thread, and still get the
- * return code.
- */
- private static final class BooleanWrapper {
- public boolean b;
- }
+ private ResourceMonitor mResourceMonitor;
+ private ArrayList<Runnable> mResourceRefreshListener = new ArrayList<Runnable>();
/**
* Custom PrintStream for Dx output. This class overrides the method
@@ -210,10 +243,14 @@
Display display = getDisplay();
+ // set the default android console.
+ mAndroidConsole = new MessageConsole("Android", null); //$NON-NLS-1$
+ ConsolePlugin.getDefault().getConsoleManager().addConsoles(
+ new IConsole[] { mAndroidConsole });
+
// get the stream to write in the android console.
- MessageConsole androidConsole = CommonPlugin.getDefault().getAndroidConsole();
- mAndroidConsoleStream = androidConsole.newMessageStream();
- mAndroidConsoleErrorStream = androidConsole.newMessageStream();
+ mAndroidConsoleStream = mAndroidConsole.newMessageStream();
+ mAndroidConsoleErrorStream = mAndroidConsole.newMessageStream();
mRed = new Color(display, 0xFF, 0x00, 0x00);
// because this can be run, in some cases, by a non ui thread, and beccause
@@ -267,22 +304,19 @@
// get the SDK location and build id.
if (checkSdkLocationAndId()) {
- // if sdk if valid, reparse the skin folder
- SkinRepository.getInstance().parseFolder(getOsSkinFolder());
+ // if sdk if valid, reparse it
+
+ // add the current Android project to the list of projects to be updated
+ // after the SDK is reloaded
+ synchronized (mPostLoadProjects) {
+ // get the project to refresh.
+ IJavaProject[] androidProjects = BaseProjectHelper.getAndroidProjects();
+ mPostLoadProjects.addAll(Arrays.asList(androidProjects));
+ }
+
+ // parse the SDK resources at the new location
+ parseSdkContent();
}
-
- // parse the SDK resources at the new location
- parseSdkContent();
-
- // get the project to refresh.
- IJavaProject[] androidProjects = BaseProjectHelper.getAndroidProjects();
-
- // Setup the new container for each project. By providing new instances of
- // AndroidClasspathContainer, this will force JDT to call
- // IClasspathContainer#getClasspathEntries() again and receive the new
- // path to the framework jar.
- AndroidClasspathContainerInitializer.updateProjects(androidProjects);
-
} else if (PREFS_BUILD_VERBOSITY.equals(property)) {
mBuildVerbosity = BuildPreferencePage.getBuildLevel(
mStore.getString(PREFS_BUILD_VERBOSITY));
@@ -299,20 +333,11 @@
}
// check the location of SDK
- if (checkSdkLocationAndId()) {
- // if sdk if valid, parse the skin folder
- SkinRepository.getInstance().parseFolder(getOsSkinFolder());
-
- // parse the SDK resources.
- parseSdkContent();
- }
+ final boolean isSdkLocationValid = checkSdkLocationAndId();
mBuildVerbosity = BuildPreferencePage.getBuildLevel(
mStore.getString(PREFS_BUILD_VERBOSITY));
- // Ping the usage start server.
- pingUsageServer();
-
// create the loader that's able to load the images
mLoader = new ImageLoader(this);
@@ -356,18 +381,31 @@
dialog.open();
}
});
+
+ // initialize editors
+ startEditors();
- /* The Editors plugin must be started as soon as Android projects are opened or created,
- * in order to properly set default editors on the layout/values XML files.
- *
- * This ensures that the default editors is really only set when a new XML file
- * is added to the workspace (IResourceDelta.ADDED event), through project creation or
- * manual add.
- * Other methods would force to go through existing projects when the Editors plugin is
- * started, and set the default editors for their XML files, possibly erasing user set
- * default editors.
- */
- startEditorsPlugin();
+ // Ping the usage server and parse the SDK content.
+ // This is deferred in separate jobs to avoid blocking the bundle start.
+ // We also serialize them to avoid too many parallel jobs when Eclipse starts.
+ Job pingJob = createPingUsageServerJob();
+ pingJob.addJobChangeListener(new JobChangeAdapter() {
+ @Override
+ public void done(IJobChangeEvent event) {
+ super.done(event);
+
+ // Once the ping job is finished, start the SDK parser
+ if (isSdkLocationValid) {
+ // parse the SDK resources.
+ parseSdkContent();
+ }
+ }
+ });
+ // build jobs are run after other interactive jobs
+ pingJob.setPriority(Job.BUILD);
+ // Wait 2 seconds before starting the ping job. This leaves some time to the
+ // other bundles to initialize.
+ pingJob.schedule(2000 /*milliseconds*/);
}
/*
@@ -379,6 +417,8 @@
public void stop(BundleContext context) throws Exception {
super.stop(context);
+ stopEditors();
+
DexWrapper.unloadDex();
mRed.dispose();
@@ -418,37 +458,22 @@
/** Returns the adb path relative to the sdk folder */
public static String getOsRelativeAdb() {
- return AndroidConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_ADB;
+ return SdkConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_ADB;
}
/** Returns the aapt path relative to the sdk folder */
public static String getOsRelativeAapt() {
- return AndroidConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_AAPT;
+ return SdkConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_AAPT;
}
/** Returns the emulator path relative to the sdk folder */
public static String getOsRelativeEmulator() {
- return AndroidConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_EMULATOR;
+ return SdkConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_EMULATOR;
}
/** Returns the aidl path relative to the sdk folder */
public static String getOsRelativeAidl() {
- return AndroidConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_AIDL;
- }
-
- /** Returns the framework jar path relative to the sdk folder */
- public static String getOsRelativeFramework() {
- return AndroidConstants.FN_FRAMEWORK_LIBRARY;
- }
-
- /** Returns the android sources path relative to the sdk folder */
- public static String getOsRelativeAndroidSources() {
- return AndroidConstants.FD_ANDROID_SOURCES;
- }
-
- /** Returns the framework jar path relative to the sdk folder */
- public static String getOsRelativeAttrsXml() {
- return AndroidConstants.OS_SDK_LIBS_FOLDER + AndroidConstants.FN_ATTRS_XML;
+ return SdkConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_AIDL;
}
/** Returns the absolute adb path */
@@ -458,7 +483,7 @@
/** Returns the absolute traceview path */
public static String getOsAbsoluteTraceview() {
- return getOsSdkFolder() + AndroidConstants.OS_SDK_TOOLS_FOLDER +
+ return getOsSdkFolder() + SdkConstants.OS_SDK_TOOLS_FOLDER +
AndroidConstants.FN_TRACEVIEW;
}
@@ -467,21 +492,6 @@
return getOsSdkFolder() + getOsRelativeAapt();
}
- /** Returns the absolute sdk framework path */
- public static String getOsAbsoluteFramework() {
- return getOsSdkFolder() + getOsRelativeFramework();
- }
-
- /** Returns the absolute android sources path in the sdk */
- public static String getOsAbsoluteAndroidSources() {
- return getOsSdkFolder() + getOsRelativeAndroidSources();
- }
-
- /** Returns the absolute attrs.xml path */
- public static String getOsAbsoluteAttrsXml() {
- return getOsSdkFolder() + getOsRelativeAttrsXml();
- }
-
/** Returns the absolute emulator path */
public static String getOsAbsoluteEmulator() {
return getOsSdkFolder() + getOsRelativeEmulator();
@@ -492,16 +502,6 @@
return getOsSdkFolder() + getOsRelativeAidl();
}
- /** Returns the absolute path to the aidl framework import file. */
- public static String getOsAbsoluteFrameworkAidl() {
- return getOsSdkFolder() + AndroidConstants.OS_SDK_LIBS_FOLDER +
- AndroidConstants.FN_FRAMEWORK_AIDL;
- }
-
- public static String getOsSdkSamplesFolder() {
- return getOsSdkFolder() + AndroidConstants.OS_SDK_SAMPLES_FOLDER;
- }
-
/**
* Returns a Url file path to the javaDoc folder.
*/
@@ -526,11 +526,7 @@
}
public static String getOsSdkToolsFolder() {
- return getOsSdkFolder() + AndroidConstants.OS_SDK_TOOLS_FOLDER;
- }
-
- public static String getOsSkinFolder() {
- return getOsSdkFolder() + AndroidConstants.OS_SDK_SKINS_FOLDER;
+ return getOsSdkFolder() + SdkConstants.OS_SDK_TOOLS_FOLDER;
}
public static synchronized boolean getAutoResRefresh() {
@@ -540,18 +536,6 @@
return sPlugin.mStore.getBoolean(PREFS_RES_AUTO_REFRESH);
}
- /**
- * Returns the SDK build id.
- * @return a string containing the SDK build id, or null it it is unknownn.
- */
- public static synchronized String getSdkApiVersion() {
- if (sPlugin != null) {
- return sPlugin.mSdkApiVersion;
- }
-
- return null;
- }
-
public static synchronized int getBuildVerbosity() {
if (sPlugin != null) {
return sPlugin.mBuildVerbosity;
@@ -705,23 +689,25 @@
final Display display = getDisplay();
// we need to ask the user what he wants to do.
- final BooleanWrapper wrapper = new BooleanWrapper();
+ final boolean[] result = new boolean[1];
display.syncExec(new Runnable() {
public void run() {
Shell shell = display.getActiveShell();
- wrapper.b = MessageDialog.openQuestion(shell, title, message);
+ result[0] = MessageDialog.openQuestion(shell, title, message);
}
});
- return wrapper.b;
+ return result[0];
}
/**
* Logs a message to the default Eclipse log.
*
- * @param severity The severity code. Valid values are: {@link IStatus#OK}, {@link IStatus#ERROR},
- * {@link IStatus#INFO}, {@link IStatus#WARNING} or {@link IStatus#CANCEL}.
+ * @param severity The severity code. Valid values are: {@link IStatus#OK},
+ * {@link IStatus#ERROR}, {@link IStatus#INFO}, {@link IStatus#WARNING} or
+ * {@link IStatus#CANCEL}.
* @param format The format string, like for {@link String#format(String, Object...)}.
- * @param args The arguments for the format string, like for {@link String#format(String, Object...)}.
+ * @param args The arguments for the format string, like for
+ * {@link String#format(String, Object...)}.
*/
public static void log(int severity, String format, Object ... args) {
String message = String.format(format, args);
@@ -845,7 +831,7 @@
// now make sure it's not docked.
ConsolePlugin.getDefault().getConsoleManager().showConsoleView(
- CommonPlugin.getDefault().getAndroidConsole());
+ AdtPlugin.getDefault().getAndroidConsole());
}
/**
@@ -883,21 +869,17 @@
}
/**
- * Adds a {@link IJavaProject} to a list of projects to be recompiled once dx.jar is loaded.
- * @param javaProject
+ * Returns whether the Sdk has been loaded. If the SDK has not been loaded, the given
+ * <var>project</var> is added to a list of projects to recompile after the SDK is loaded.
*/
- public void addPostDexProject(IJavaProject javaProject) {
- synchronized (mPostDexProjects) {
- if (DexWrapper.getStatus() == DexWrapper.LoadStatus.LOADED) {
- // Setup the new container for each project. By providing new instances of
- // AndroidClasspathContainer, this will force JDT to call
- // IClasspathContainer#getClasspathEntries() again and receive the new
- // path to the framework jar, and the project will be recompiled.
- AndroidClasspathContainerInitializer.updateProjects(new IJavaProject [] {
- javaProject });
- } else {
- mPostDexProjects.add(javaProject);
+ public LoadStatus getSdkLoadStatus(IJavaProject project) {
+ synchronized (mPostLoadProjects) {
+ // only add the project to the list, if we are still loading.
+ if (mSdkIsLoaded == LoadStatus.LOADING && project != null) {
+ mPostLoadProjects.add(project);
}
+
+ return mSdkIsLoaded;
}
}
@@ -907,9 +889,6 @@
* @return false if the location is not correct.
*/
private boolean checkSdkLocationAndId() {
- // Reset the sdk build first in case the SDK is invalid and we abort.
- mSdkApiVersion = null;
-
if (mOsSdkLocation == null || mOsSdkLocation.length() == 0) {
displayError(Messages.Dialog_Title_SDK_Location, Messages.SDK_Not_Setup);
return false;
@@ -949,17 +928,16 @@
String.format(Messages.Could_Not_Find_Folder, osSdkLocation));
}
- String osTools = osSdkLocation + AndroidConstants.OS_SDK_TOOLS_FOLDER;
+ String osTools = osSdkLocation + SdkConstants.OS_SDK_TOOLS_FOLDER;
File toolsFolder = new File(osTools);
if (toolsFolder.isDirectory() == false) {
return errorHandler.handleError(
String.format(Messages.Could_Not_Find_Folder_In_SDK,
- AndroidConstants.FD_TOOLS, osSdkLocation));
+ SdkConstants.FD_TOOLS, osSdkLocation));
}
// check the path to various tools we use
String[] filesToCheck = new String[] {
- osSdkLocation + getOsRelativeFramework(),
osSdkLocation + getOsRelativeAdb(),
osSdkLocation + getOsRelativeAapt(),
osSdkLocation + getOsRelativeAidl(),
@@ -990,118 +968,106 @@
}
/**
- * Pings the usage start server.
+ * Creates a job than can ping the usage server.
*/
- private void pingUsageServer() {
+ private Job createPingUsageServerJob() {
// In order to not block the plugin loading, so we spawn another thread.
- new Thread("Ping!") { //$NON-NLS-1$
+ Job job = new Job("Android SDK Ping") { // Job name, visible in progress view
@Override
- public void run() {
- // get the version of the plugin
- String versionString = (String) getBundle().getHeaders().get(
- Constants.BUNDLE_VERSION);
- Version version = new Version(versionString);
-
- SdkStatsHelper.pingUsageServer("adt", version); //$NON-NLS-1$
- }
- }.start();
- }
-
- /**
- * Starts the Editors plugin.
- * <p/>
- * Since we do not want any dependencies between the plugins (Editors is an optional
- * plugin not needed for Android development), we attempt to start the plugin through
- * OSGi directly.
- * <p/>
- * This is done in another thread to not delay the start of this plugin.
- */
- private void startEditorsPlugin() {
- new Thread() {
- @Override
- public void run() {
+ protected IStatus run(IProgressMonitor monitor) {
try {
- // look for the bundle of the Editors plugin
- Bundle editorsBundle = Platform.getBundle(AndroidConstants.EDITORS_PLUGIN_ID);
- if (editorsBundle != null) {
- // we only start if the bundle is installed and not started.
- // STARTING means that its start is pending a triggering.
- int bundleState = editorsBundle.getState();
- if ((bundleState & (Bundle.RESOLVED | Bundle.INSTALLED
- | Bundle.STARTING)) != 0) {
- // Attempt to start it.
- // START_TRANSIENT is used because we don't want
- // to change the auto start value.
- editorsBundle.start(Bundle.START_TRANSIENT);
- }
- }
- } catch (Exception e) {
- log(e, Messages.AdtPlugin_Failed_To_Start_s, AndroidConstants.EDITORS_PLUGIN_ID);
+
+ // get the version of the plugin
+ String versionString = (String) getBundle().getHeaders().get(
+ Constants.BUNDLE_VERSION);
+ Version version = new Version(versionString);
+
+ SdkStatsHelper.pingUsageServer("editors", version); //$NON-NLS-1$
+
+ return Status.OK_STATUS;
+ } catch (Throwable t) {
+ log(t, "pingUsageServer failed"); //$NON-NLS-1$
+ return new Status(IStatus.ERROR, PLUGIN_ID,
+ "pingUsageServer failed", t);
}
}
- }.start();
+ };
+ return job;
}
/**
- * Parses the SDK resources and set them in the {@link FrameworkResourceManager}.
+ * Parses the SDK resources.
*/
private void parseSdkContent() {
// Perform the update in a thread (here an Eclipse runtime job)
// since this should never block the caller (especially the start method)
- new Job(Messages.AdtPlugin_Android_SDK_Content_Loader) {
+ Job job = new Job(Messages.AdtPlugin_Android_SDK_Content_Loader) {
+ @SuppressWarnings("unchecked")
@Override
protected IStatus run(IProgressMonitor monitor) {
- try {
- SubMonitor progress = null;
- try {
- progress = SubMonitor.convert(monitor, Messages.AdtPlugin_Parsing_Resources, 100);
-
- // load the values.
- FrameworkResourceParser parser = new FrameworkResourceParser();
- parser.parse(mOsSdkLocation, FrameworkResourceManager.getInstance(),
- progress);
-
- // set the location of the layout lib jar file.
- FrameworkResourceManager.getInstance().setLayoutLibLocation(
- mOsSdkLocation + AndroidConstants.OS_SDK_LIBS_LAYOUTLIB_JAR);
- FrameworkResourceManager.getInstance().setFrameworkResourcesLocation(
- mOsSdkLocation + AndroidConstants.OS_SDK_RESOURCES_FOLDER);
- FrameworkResourceManager.getInstance().setFrameworkFontLocation(
- mOsSdkLocation + AndroidConstants.OS_SDK_FONTS_FOLDER);
- } catch (Throwable e) {
- AdtPlugin.log(e, "Android SDK Resource Parser failed"); //$NON-NLS-1$
- AdtPlugin.printErrorToConsole(Messages.AdtPlugin_Android_SDK_Resource_Parser,
- Messages.AdtPlugin_Failed_To_Parse_s + e.getMessage());
-
- return new Status(IStatus.ERROR, PLUGIN_ID, e.getMessage(), e);
- } finally {
- if (progress != null) {
- progress.worked(100);
- }
- }
+ try {
+ SubMonitor progress = SubMonitor.convert(monitor,
+ "Initialize SDK Manager", 100);
- try {
- progress = SubMonitor.convert(monitor, Messages.AdtPlugin_Parsing_Resources, 20);
+ Sdk sdk = Sdk.loadSdk(mOsSdkLocation);
+
+ if (sdk != null) {
+
+ progress.setTaskName(Messages.AdtPlugin_Parsing_Resources);
+
+ for (IAndroidTarget target : sdk.getTargets()) {
+ IStatus status = new AndroidTargetParser(target).run(progress);
+ if (status.getCode() != IStatus.OK) {
+ synchronized (mPostLoadProjects) {
+ mSdkIsLoaded = LoadStatus.FAILED;
+ mPostLoadProjects.clear();
+ }
+ return status;
+ }
+ }
+
+ // FIXME: move this per platform, or somewhere else.
+ progress = SubMonitor.convert(monitor,
+ Messages.AdtPlugin_Parsing_Resources, 20);
DexWrapper.unloadDex();
IStatus res = DexWrapper.loadDex(
mOsSdkLocation + AndroidConstants.OS_SDK_LIBS_DX_JAR);
if (res != Status.OK_STATUS) {
+ synchronized (mPostLoadProjects) {
+ mSdkIsLoaded = LoadStatus.FAILED;
+ mPostLoadProjects.clear();
+ }
return res;
- } else {
+ }
+
+ synchronized (mPostLoadProjects) {
+ mSdkIsLoaded = LoadStatus.LOADED;
+
// update the project that needs recompiling.
- synchronized (mPostDexProjects) {
- if (mPostDexProjects.size() > 0) {
- IJavaProject[] array = mPostDexProjects.toArray(
- new IJavaProject[mPostDexProjects.size()]);
- AndroidClasspathContainerInitializer.updateProjects(array);
- mPostDexProjects.clear();
- }
+ if (mPostLoadProjects.size() > 0) {
+ IJavaProject[] array = mPostLoadProjects.toArray(
+ new IJavaProject[mPostLoadProjects.size()]);
+ AndroidClasspathContainerInitializer.updateProjects(array);
+ mPostLoadProjects.clear();
}
}
- } finally {
- if (progress != null) {
- progress.worked(20);
+ }
+
+ // Notify resource changed listeners
+ progress.subTask("Refresh UI");
+ progress.setWorkRemaining(mResourceRefreshListener.size());
+
+ // Clone the list before iterating, to avoid Concurrent Modification
+ // exceptions
+ List<Runnable> listeners = (List<Runnable>)mResourceRefreshListener.clone();
+ for (Runnable listener : listeners) {
+ try {
+ AdtPlugin.getDisplay().syncExec(listener);
+ } catch (Exception e) {
+ AdtPlugin.log(e, "ResourceRefreshListener Failed"); //$NON-NLS-1$
+ } finally {
+ progress.worked(1);
}
}
} finally {
@@ -1112,6 +1078,252 @@
return Status.OK_STATUS;
}
- }.schedule();
+ };
+ job.setPriority(Job.BUILD); // build jobs are run after other interactive jobs
+ job.schedule();
+ }
+
+ /** Returns the global android console */
+ public MessageConsole getAndroidConsole() {
+ return mAndroidConsole;
+ }
+
+ // ----- Methods for Editors -------
+
+ public void startEditors() {
+ sAndroidLogoDesc = imageDescriptorFromPlugin(AdtPlugin.PLUGIN_ID,
+ "/icons/android.png"); //$NON-NLS-1$
+ sAndroidLogo = sAndroidLogoDesc.createImage();
+
+ // get the stream to write in the android console.
+ MessageConsole androidConsole = AdtPlugin.getDefault().getAndroidConsole();
+ mAndroidConsoleStream = androidConsole.newMessageStream();
+
+ mAndroidConsoleErrorStream = androidConsole.newMessageStream();
+ mRed = new Color(getDisplay(), 0xFF, 0x00, 0x00);
+
+ // because this can be run, in some cases, by a non ui thread, and beccause
+ // changing the console properties update the ui, we need to make this change
+ // in the ui thread.
+ getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ mAndroidConsoleErrorStream.setColor(mRed);
+ }
+ });
+
+ // Add a resource listener to handle compiled resources.
+ IWorkspace ws = ResourcesPlugin.getWorkspace();
+ mResourceMonitor = ResourceMonitor.startMonitoring(ws);
+
+ if (mResourceMonitor != null) {
+ try {
+ setupDefaultEditor(mResourceMonitor);
+ ResourceManager.setup(mResourceMonitor);
+ } catch (Throwable t) {
+ log(t, "ResourceManager.setup failed"); //$NON-NLS-1$
+ }
+ }
+ }
+
+ /**
+ * The <code>AbstractUIPlugin</code> implementation of this <code>Plugin</code>
+ * method saves this plug-in's preference and dialog stores and shuts down
+ * its image registry (if they are in use). Subclasses may extend this
+ * method, but must send super <b>last</b>. A try-finally statement should
+ * be used where necessary to ensure that <code>super.shutdown()</code> is
+ * always done.
+ *
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stopEditors() {
+ sAndroidLogo.dispose();
+
+ IconFactory.getInstance().Dispose();
+
+ // Remove the resource listener that handles compiled resources.
+ IWorkspace ws = ResourcesPlugin.getWorkspace();
+ ResourceMonitor.stopMonitoring(ws);
+
+ mRed.dispose();
+ }
+
+ /**
+ * Returns an Image for the small Android logo.
+ *
+ * Callers should not dispose it.
+ */
+ public static Image getAndroidLogo() {
+ return sAndroidLogo;
+ }
+
+ /**
+ * Returns an {@link ImageDescriptor} for the small Android logo.
+ *
+ * Callers should not dispose it.
+ */
+ public static ImageDescriptor getAndroidLogoDesc() {
+ return sAndroidLogoDesc;
+ }
+
+ /**
+ * Returns the ResourceMonitor object.
+ */
+ public ResourceMonitor getResourceMonitor() {
+ return mResourceMonitor;
+ }
+
+ /**
+ * Sets up the editor to register default editors for resource files when needed.
+ *
+ * This is called by the {@link AdtPlugin} during initialization.
+ *
+ * @param monitor The main Resource Monitor object.
+ */
+ public void setupDefaultEditor(ResourceMonitor monitor) {
+ monitor.addFileListener(new IFileListener() {
+
+ private static final String UNKNOWN_EDITOR = "unknown-editor"; //$NON-NLS-1$
+
+ /* (non-Javadoc)
+ * Sent when a file changed.
+ * @param file The file that changed.
+ * @param markerDeltas The marker deltas for the file.
+ * @param kind The change kind. This is equivalent to
+ * {@link IResourceDelta#accept(IResourceDeltaVisitor)}
+ *
+ * @see IFileListener#fileChanged
+ */
+ public void fileChanged(IFile file, IMarkerDelta[] markerDeltas, int kind) {
+ if (AndroidConstants.EXT_XML.equals(file.getFileExtension())) {
+ // The resources files must have a file path similar to
+ // project/res/.../*.xml
+ // There is no support for sub folders, so the segment count must be 4
+ if (file.getFullPath().segmentCount() == 4) {
+ // check if we are inside the res folder.
+ String segment = file.getFullPath().segment(1);
+ if (segment.equalsIgnoreCase(AndroidConstants.FD_RESOURCES)) {
+ // we are inside a res/ folder, get the actual ResourceFolder
+ ProjectResources resources = ResourceManager.getInstance().
+ getProjectResources(file.getProject());
+
+ // This happens when importing old Android projects in Eclipse
+ // that lack the container (probably because resources fail to build
+ // properly.)
+ if (resources == null) {
+ log(IStatus.INFO,
+ "getProjectResources failed for path %1$s in project %2$s", //$NON-NLS-1$
+ file.getFullPath().toOSString(),
+ file.getProject().getName());
+ return;
+ }
+
+ ResourceFolder resFolder = resources.getResourceFolder(
+ (IFolder)file.getParent());
+
+ if (resFolder != null) {
+ if (kind == IResourceDelta.ADDED) {
+ resourceAdded(file, resFolder.getType());
+ } else if (kind == IResourceDelta.CHANGED) {
+ resourceChanged(file, resFolder.getType());
+ }
+ } else {
+ // if the res folder is null, this means the name is invalid,
+ // in this case we remove whatever android editors that was set
+ // as the default editor.
+ IEditorDescriptor desc = IDE.getDefaultEditor(file);
+ String editorId = desc.getId();
+ if (editorId.startsWith(AndroidConstants.EDITORS_NAMESPACE)) {
+ // reset the default editor.
+ IDE.setDefaultEditor(file, null);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void resourceAdded(IFile file, ResourceFolderType type) {
+ // set the default editor based on the type.
+ if (type == ResourceFolderType.LAYOUT) {
+ IDE.setDefaultEditor(file, LayoutEditor.ID);
+ } else if (type == ResourceFolderType.DRAWABLE
+ || type == ResourceFolderType.VALUES) {
+ IDE.setDefaultEditor(file, ResourcesEditor.ID);
+ } else if (type == ResourceFolderType.MENU) {
+ IDE.setDefaultEditor(file, MenuEditor.ID);
+ } else if (type == ResourceFolderType.XML) {
+ if (XmlEditor.canHandleFile(file)) {
+ IDE.setDefaultEditor(file, XmlEditor.ID);
+ } else {
+ // set a property to determine later if the XML can be handled
+ QualifiedName qname = new QualifiedName(
+ AdtPlugin.PLUGIN_ID,
+ UNKNOWN_EDITOR);
+ try {
+ file.setPersistentProperty(qname, "1");
+ } catch (CoreException e) {
+ // pass
+ }
+ }
+ }
+ }
+
+ private void resourceChanged(IFile file, ResourceFolderType type) {
+ if (type == ResourceFolderType.XML) {
+ IEditorDescriptor ed = IDE.getDefaultEditor(file);
+ if (ed == null || ed.getId() != XmlEditor.ID) {
+ QualifiedName qname = new QualifiedName(
+ AdtPlugin.PLUGIN_ID,
+ UNKNOWN_EDITOR);
+ String prop = null;
+ try {
+ prop = file.getPersistentProperty(qname);
+ } catch (CoreException e) {
+ // pass
+ }
+ if (prop != null && XmlEditor.canHandleFile(file)) {
+ try {
+ // remove the property & set editor
+ file.setPersistentProperty(qname, null);
+ IWorkbenchPage page = PlatformUI.getWorkbench().
+ getActiveWorkbenchWindow().getActivePage();
+
+ IEditorPart oldEditor = page.findEditor(new FileEditorInput(file));
+ if (oldEditor != null &&
+ AdtPlugin.displayPrompt("Android XML Editor",
+ String.format("The file you just saved as been recognized as a file that could be better handled using the Android XML Editor. Do you want to edit '%1$s' using the Android XML editor instead?",
+ file.getFullPath()))) {
+ IDE.setDefaultEditor(file, XmlEditor.ID);
+ IEditorPart newEditor = page.openEditor(
+ new FileEditorInput(file),
+ XmlEditor.ID,
+ true, /* activate */
+ IWorkbenchPage.MATCH_NONE);
+
+ if (newEditor != null) {
+ page.closeEditor(oldEditor, true /* save */);
+ }
+ }
+ } catch (CoreException e) {
+ // setPersistentProperty or page.openEditor may have failed
+ }
+ }
+ }
+ }
+ }
+
+ }, IResourceDelta.ADDED | IResourceDelta.CHANGED);
+ }
+
+ public void addResourceChangedListener(Runnable resourceRefreshListener) {
+ mResourceRefreshListener.add(resourceRefreshListener);
+ }
+
+ public void removeResourceChangedListener(Runnable resourceRefreshListener) {
+ mResourceRefreshListener.remove(resourceRefreshListener);
+ }
+
+ public static synchronized OutputStream getErrorStream() {
+ return sPlugin.mAndroidConsoleErrorStream;
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/VersionCheck.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/VersionCheck.java
index bac940a..6d85af3 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/VersionCheck.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/VersionCheck.java
@@ -16,9 +16,8 @@
package com.android.ide.eclipse.adt;
-import com.android.ddmlib.Device;
import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler;
-import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.sdklib.SdkConstants;
import org.osgi.framework.Constants;
import org.osgi.framework.Version;
@@ -42,19 +41,6 @@
*
*/
final class VersionCheck {
-
- /** Pattern to get the SDK build incremental version from the
- * <code>$SDK/tools/lib/build.prop file</code>. */
- private final static Pattern sBuildVersionPattern = Pattern.compile(
- "^" + Device.PROP_BUILD_VERSION + "=(.+)$"); //$NON-NLS-1$
-
- /**
- * Pattern to parse release type SDK version number. This parses the content read with
- * <code>sBuildIdPattern</code>.
- */
- private final static Pattern sSdkVersionPattern = Pattern.compile(
- "^(\\d+)\\.(\\d+)_r(\\d+)$", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
-
/**
* Pattern to get the minimum plugin version supported by the SDK. This is read from
* the file <code>$SDK/tools/lib/plugin.prop</code>.
@@ -69,58 +55,7 @@
*/
public static boolean checkVersion(String osSdkPath, CheckSdkErrorHandler errorHandler) {
AdtPlugin plugin = AdtPlugin.getDefault();
- String osLibs = osSdkPath + AndroidConstants.OS_SDK_LIBS_FOLDER;
-
- /*
- * All plugins should work with all SDKs. Newer SDKs may require a newer plugin
- * but this is handled below.
- * Still, we need to grab the SDK version from this file. This is used
- * to compare to running emulator/device when launching run/debug sessions.
- */
- try {
- FileReader reader = new FileReader(osLibs + AndroidConstants.FN_BUILD_PROP);
- BufferedReader bReader = new BufferedReader(reader);
- String line;
- while ((line = bReader.readLine()) != null) {
- Matcher m = sBuildVersionPattern.matcher(line);
- if (m.matches()) {
- plugin.mSdkApiVersion = m.group(1).trim();
-
- /*
- * No checks on the version at the moment.
- */
- /*
- if (plugin.mSdkBuildVersion != null) {
- // attempt to get version number from the build id
- m = sSdkVersionPattern.matcher(plugin.mSdkBuildVersion);
- if (m.matches()) {
- // get the platform version number
- int platformMajor = Integer.parseInt(m.group(1));
- int platformMinor = Integer.parseInt(m.group(2));
- @SuppressWarnings("unused") //$NON-NLS-1$
- int sdkRelease = Integer.parseInt(m.group(3));
-
- if (platformMajor != 0 || platformMinor != 9) {
- return errorHandler.handleError(String.format(
- "This version of ADT requires the Android SDK version 0.9\n\nCurrent version is %1$s.\n\nPlease update your SDK to the latest version.",
- plugin.mSdkBuildVersion));
- }
- } else {
- // unknown version format.
- AdtPlugin.printErrorToConsole(
- (Object)String.format(Messages.VersionCheck_Unable_To_Parse_Version_s,
- plugin.mSdkBuildVersion));
- }
- }
- */
- break;
- }
- }
- } catch (FileNotFoundException e) {
- // the build id will be null, and this is handled by the builders.
- } catch (IOException e) {
- // the build id will be null, and this is handled by the builders.
- }
+ String osLibs = osSdkPath + SdkConstants.OS_SDK_TOOLS_LIB_FOLDER;
// get the plugin property file, and grab the minimum plugin version required
// to work with the sdk
@@ -128,7 +63,7 @@
int minMinorVersion = -1;
int minMicroVersion = -1;
try {
- FileReader reader = new FileReader(osLibs + AndroidConstants.FN_PLUGIN_PROP);
+ FileReader reader = new FileReader(osLibs + SdkConstants.FN_PLUGIN_PROP);
BufferedReader bReader = new BufferedReader(reader);
String line;
while ((line = bReader.readLine()) != null) {
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java
index 0b1b647..4d16120 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java
@@ -19,6 +19,8 @@
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.sdk.LoadStatus;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
import com.android.jarutils.DebugKeyProvider;
@@ -28,6 +30,7 @@
import com.android.jarutils.DebugKeyProvider.KeytoolException;
import com.android.jarutils.SignedJarBuilder.IZipEntryFilter;
import com.android.prefs.AndroidLocation.AndroidLocationException;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
@@ -44,6 +47,7 @@
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
@@ -296,6 +300,15 @@
saveProjectBooleanProperty(PROPERTY_PACKAGE_RESOURCES, mPackageResources);
saveProjectBooleanProperty(PROPERTY_BUILD_APK, mBuildFinalPackage);
+ // At this point, we can abort the build if we have to, as we have computed
+ // our resource delta and stored the result.
+
+ // check if we have finished loading the SDK.
+ if (AdtPlugin.getDefault().getSdkLoadStatus(javaProject) != LoadStatus.LOADED) {
+ // we exit silently
+ return referencedProjects;
+ }
+
// Now check the compiler compliance level, not displaying the error
// message since this is not the first builder.
if (ProjectHelper.checkCompilerCompliance(getProject())
@@ -502,7 +515,8 @@
commandArray.add(osAssetsPath);
}
commandArray.add("-I"); //$NON-NLS-1$
- commandArray.add(AdtPlugin.getOsAbsoluteFramework());
+ commandArray.add(
+ Sdk.getCurrent().getTarget(project).getPath(IAndroidTarget.ANDROID_JAR));
commandArray.add("-F"); //$NON-NLS-1$
commandArray.add(osOutFilePath);
@@ -584,16 +598,9 @@
DexWrapper wrapper = DexWrapper.getWrapper();
if (wrapper == null) {
- if (DexWrapper.getStatus() == DexWrapper.LoadStatus.FAILED) {
+ if (DexWrapper.getStatus() == LoadStatus.FAILED) {
throw new CoreException(new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
Messages.ApkBuilder_UnableBuild_Dex_Not_loaded));
- } else {
- // means we haven't loaded the dex jar yet.
- // We set the project to be recompiled after dex is loaded.
- AdtPlugin.getDefault().addPostDexProject(javaProject);
-
- // and we exit silently
- return false;
}
}
@@ -677,7 +684,7 @@
}
// TODO: get the store type from somewhere else.
- DebugKeyProvider provider = new DebugKeyProvider(null /* storeType */,
+ DebugKeyProvider provider = new DebugKeyProvider(osKeyPath, null /* storeType */,
new IKeyGenOutput() {
public void err(String message) {
AdtPlugin.printErrorToConsole(javaProject.getProject(),
@@ -747,9 +754,18 @@
}
}
+ // now write the native libraries.
+ // First look if the lib folder is there.
+ IResource libFolder = javaProject.getProject().findMember(
+ AndroidConstants.FD_NATIVE_LIBS);
+ if (libFolder != null && libFolder.exists() &&
+ libFolder.getType() == IResource.FOLDER) {
+ // look inside and put .so in lib/* by keeping the relative folder path.
+ writeNativeLibraries(libFolder.getFullPath().segmentCount(), builder, libFolder);
+ }
+
// close the jar file and write the manifest and sign it.
builder.close();
-
} catch (GeneralSecurityException e1) {
// mark project and return
String msg = String.format(Messages.Final_Archive_Error_s, e1.getMessage());
@@ -784,6 +800,12 @@
// and also output it in the console
AdtPlugin.printErrorToConsole(javaProject.getProject(), msg);
+ } catch (CoreException e) {
+ // mark project and return
+ String msg = String.format(Messages.Final_Archive_Error_s, e.getMessage());
+ AdtPlugin.printErrorToConsole(javaProject.getProject(), msg);
+ markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
+ return false;
} finally {
if (fos != null) {
try {
@@ -798,6 +820,48 @@
}
/**
+ * Writes native libraries into a {@link SignedJarBuilder}.
+ * <p/>This recursively go through folder and writes .so files.
+ * The path in the archive is based on the root folder containing the libraries in the project.
+ * Its segment count is passed to the method to compute the resources path relative to the root
+ * folder.
+ * Native libraries in the archive must be in a "lib" folder. Everything in the project native
+ * lib folder directly goes in this "lib" folder in the archive.
+ *
+ *
+ * @param rooSegmentCount The number of segment of the path of the folder containing the
+ * libraries. This is used to compute the path in the archive.
+ * @param jarBuilder the {@link SignedJarBuilder} used to create the archive.
+ * @param resource the IResource to write.
+ * @throws CoreException
+ * @throws IOException
+ */
+ private void writeNativeLibraries(int rootSegmentCount, SignedJarBuilder jarBuilder,
+ IResource resource) throws CoreException, IOException {
+ if (resource.getType() == IResource.FILE) {
+ IPath path = resource.getFullPath();
+
+ // check the extension.
+ if (path.getFileExtension().equalsIgnoreCase(AndroidConstants.EXT_NATIVE_LIB)) {
+ // remove the first segment to build the path inside the archive.
+ path = path.removeFirstSegments(rootSegmentCount);
+
+ // add it to the archive.
+ IPath apkPath = new Path(AndroidConstants.FD_APK_NATIVE_LIBS);
+ apkPath = apkPath.append(path);
+
+ // writes the file in the apk.
+ jarBuilder.writeFile(resource.getLocation().toFile(), apkPath.toString());
+ }
+ } else if (resource.getType() == IResource.FOLDER) {
+ IResource[] members = ((IFolder)resource).members();
+ for (IResource member : members) {
+ writeNativeLibraries(rootSegmentCount, jarBuilder, member);
+ }
+ }
+ }
+
+ /**
* Writes the standard resources of a project and its referenced projects
* into a {@link SignedJarBuilder}.
* Standard resources are non java/aidl files placed in the java package folders.
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkDeltaVisitor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkDeltaVisitor.java
index fb60fdb..47ef626 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkDeltaVisitor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkDeltaVisitor.java
@@ -42,6 +42,7 @@
* <li>Any change to the classes.dex inside the output folder</li>
* <li>Any change to the packaged resources file inside the output folder</li>
* <li>Any change to a non java/aidl file inside the source folders</li>
+ * <li>Any change to .so file inside the lib (native library) folder</li>
* </ul>
*/
public class ApkDeltaVisitor extends BaseDeltaVisitor
@@ -79,6 +80,8 @@
private IPath mResPath;
+ private IPath mLibFolder;
+
/**
* Builds the object with a specified output folder.
* @param builder the xml builder using this object to visit the
@@ -104,6 +107,11 @@
if (resFolder != null) {
mResPath = resFolder.getFullPath();
}
+
+ IResource libFolder = builder.getProject().findMember(AndroidConstants.FD_NATIVE_LIBS);
+ if (libFolder != null) {
+ mLibFolder = libFolder.getFullPath();
+ }
}
public boolean getConvertToDex() {
@@ -161,6 +169,7 @@
// check the other folders.
if (mOutputPath != null && mOutputPath.isPrefixOf(path)) {
+ // a resource changed inside the output folder.
if (type == IResource.FILE) {
// just check this is a .class file. Any modification will
// trigger a change in the classes.dex file
@@ -217,6 +226,17 @@
mPackageResources = true;
mMakeFinalPackage = true;
return false;
+ } else if (mLibFolder != null && mLibFolder.isPrefixOf(path)) {
+ // inside the native library folder. Test if the changed resource is a .so file.
+ if (type == IResource.FILE &&
+ path.getFileExtension().equalsIgnoreCase(AndroidConstants.EXT_NATIVE_LIB)) {
+ mMakeFinalPackage = true;
+ return false; // return false for file.
+ }
+
+ // for folders, return true only if we don't already know we have to make the
+ // final package.
+ return mMakeFinalPackage == false;
} else {
// we are in a folder that is neither the resource folders, nor the output.
// check against all the source folders, unless we already know we need to do
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java
index f79be3d..f94bdc7 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java
@@ -806,12 +806,6 @@
// get the IPath
IPath path = e.getPath();
- // get the file name. if it's the framework jar, we ignore that file.
- // since we now use classpath container, this is here for legacy purpose only.
- if (AndroidConstants.FN_FRAMEWORK_LIBRARY.equals(path.lastSegment())) {
- continue;
- }
-
// check the name ends with .jar
if (AndroidConstants.EXT_JAR.equalsIgnoreCase(path.getFileExtension())) {
boolean local = false;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/DexWrapper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/DexWrapper.java
index 9ba4026..cba8ad7 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/DexWrapper.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/DexWrapper.java
@@ -17,6 +17,7 @@
package com.android.ide.eclipse.adt.build;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.LoadStatus;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
@@ -47,9 +48,6 @@
private static DexWrapper sWrapper;
- /** Status for the Loading of the dex jar file */
- public enum LoadStatus { LOADING, LOADED, FAILED }
-
private static LoadStatus sLoadStatus = LoadStatus.LOADING;
private Method mRunMethod;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java
index 850a79a..1a4aa8c 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java
@@ -18,14 +18,16 @@
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.editors.java.ReadOnlyJavaEditor;
import com.android.ide.eclipse.adt.project.FixLaunchConfig;
import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.sdk.LoadStatus;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestHelper;
import com.android.ide.eclipse.common.project.AndroidManifestParser;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
import com.android.ide.eclipse.common.project.XmlErrorHandler.BasicXmlErrorListener;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
@@ -44,7 +46,6 @@
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.ui.ide.IDE;
import java.io.IOException;
import java.util.ArrayList;
@@ -130,7 +131,6 @@
mSource);
try {
mNewFile.setDerived(true);
- IDE.setDefaultEditor(mNewFile, ReadOnlyJavaEditor.ID);
} catch (CoreException e) {
// This really shouldn't happen since we check that the resource exist.
// Worst case scenario, the resource isn't marked as derived.
@@ -266,8 +266,14 @@
// record the state
mCompileResources |= dv.getCompileResources();
- mergeAidlFileModifications(dv.getAidlToCompile(),
- dv.getAidlToRemove());
+
+ // handle aidl modification
+ if (dv.getFullAidlRecompilation()) {
+ buildAidlCompilationList(project, sourceList);
+ } else {
+ mergeAidlFileModifications(dv.getAidlToCompile(),
+ dv.getAidlToRemove());
+ }
// if there was some XML errors, we just return w/o doing
// anything since we've put some markers in the files anyway.
@@ -290,6 +296,12 @@
// At this point we have stored what needs to be build, so we can
// do some high level test and abort if needed.
+ // check if we have finished loading the SDK.
+ if (AdtPlugin.getDefault().getSdkLoadStatus(javaProject) != LoadStatus.LOADED) {
+ // we exit silently
+ return null;
+ }
+
// check the compiler compliance level, not displaying the error message
// since this is not the first builder.
if (ProjectHelper.checkCompilerCompliance(getProject())
@@ -302,13 +314,19 @@
// Check that the SDK directory has been setup.
String osSdkFolder = AdtPlugin.getOsSdkFolder();
- if (osSdkFolder.length() == 0) {
+ if (osSdkFolder == null || osSdkFolder.length() == 0) {
AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
Messages.No_SDK_Setup_Error);
markProject(AdtConstants.MARKER_ADT, Messages.No_SDK_Setup_Error,
IMarker.SEVERITY_ERROR);
return null;
}
+
+ IAndroidTarget projectTarget = Sdk.getCurrent().getTarget(project);
+ if (projectTarget == null) {
+ // no target. error has been output by the container initializer: exit silently.
+ return null;
+ }
// get the manifest file
IFile manifest = AndroidManifestHelper.getManifest(project);
@@ -448,7 +466,7 @@
array.add("-S"); //$NON-NLS-1$
array.add(osResPath);
array.add("-I"); //$NON-NLS-1$
- array.add(AdtPlugin.getOsAbsoluteFramework());
+ array.add(projectTarget.getPath(IAndroidTarget.ANDROID_JAR));
if (AdtPlugin.getBuildVerbosity() == AdtConstants.BUILD_VERBOSE) {
StringBuilder sb = new StringBuilder();
@@ -563,6 +581,8 @@
deleteObsoleteGeneratedClass(AndroidConstants.FN_MANIFEST_CLASS,
mManifestPackageSourceFolder, mManifestPackage);
}
+
+ // FIXME: delete all java generated from aidl.
}
@Override
@@ -736,12 +756,14 @@
if (mAidlToCompile.size() == 0 && mAidlToRemove.size() == 0) {
return false;
}
+
// create the command line
String[] command = new String[4 + sourceFolders.size() + (folderAidlPath != null ? 1 : 0)];
int index = 0;
+ int aidlIndex;
command[index++] = AdtPlugin.getOsAbsoluteAidl();
- command[index++] = "-p" + AdtPlugin.getOsAbsoluteFrameworkAidl(); //$NON-NLS-1$
+ command[aidlIndex = index++] = "-p"; //$NON-NLS-1$
if (folderAidlPath != null) {
command[index++] = "-p" + folderAidlPath; //$NON-NLS-1$
}
@@ -813,6 +835,8 @@
prepareFileForExternalModification(javaFile);
// finish to set the command line.
+ command[aidlIndex] = "-p" + Sdk.getCurrent().getTarget(aidlFile.getProject()).getPath(
+ IAndroidTarget.ANDROID_AIDL); //$NON-NLS-1$
command[index] = osPath;
command[index + 1] = osJavaPath;
@@ -922,7 +946,8 @@
}
/**
- * Goes through the buildpath and fills the list of aidl files to compile.
+ * Goes through the build paths and fills the list of aidl files to compile
+ * ({@link #mAidlToCompile}).
* @param project The project.
* @param buildPaths The list of build paths.
*/
@@ -977,7 +1002,7 @@
scanContainerForAidl((IFolder)r);
break;
default:
- // this would mean it's a project or the workspaceroot
+ // this would mean it's a project or the workspace root
// which is unlikely to happen. we do nothing
break;
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java
index 9c3bc5c..33d5fa6 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java
@@ -42,6 +42,7 @@
class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
IResourceDeltaVisitor {
+ // Result fields.
/**
* Compile flag. This is set to true if one of the changed/added/removed
* file is a resource file. Upon visiting all the delta resources, if
@@ -50,6 +51,22 @@
*/
private boolean mCompileResources = false;
+ /** List of .aidl files found that are modified or new. */
+ private final ArrayList<IFile> mAidlToCompile = new ArrayList<IFile>();
+
+ /** List of .aidl files that have been removed. */
+ private final ArrayList<IFile> mAidlToRemove = new ArrayList<IFile>();
+
+ /** Aidl forced recompilation flag. This is set to true if project.aidl is modified. */
+ private boolean mFullAidlCompilation = false;
+
+ /** Manifest check/parsing flag. */
+ private boolean mCheckedManifestXml = false;
+
+ /** Application Pacakge, gathered from the parsing of the manifest */
+ private String mJavaPackage = null;
+
+ // Internal usage fields.
/**
* In Resource folder flag. This allows us to know if we're in the
* resource folder.
@@ -65,14 +82,6 @@
/** List of source folders. */
private ArrayList<IPath> mSourceFolders;
- /** List of .aidl files found that are modified or new. */
- private final ArrayList<IFile> mAidlToCompile = new ArrayList<IFile>();
-
- /** List of .aidl files that have been removed. */
- private final ArrayList<IFile> mAidlToRemove = new ArrayList<IFile>();
-
- private boolean mCheckedManifestXml = false;
- private String mJavaPackage = null;
public PreCompilerDeltaVisitor(BaseBuilder builder, ArrayList<IPath> sourceFolders) {
super(builder);
@@ -90,6 +99,10 @@
public ArrayList<IFile> getAidlToRemove() {
return mAidlToRemove;
}
+
+ public boolean getFullAidlRecompilation() {
+ return mFullAidlCompilation;
+ }
/**
* Returns whether the manifest file was parsed/checked for error during the resource delta
@@ -100,7 +113,7 @@
}
/**
- * Returns the manifest package if the manifest was checked.
+ * Returns the manifest package if the manifest was checked/parsed.
* <p/>
* This can return null in two cases:
* <ul>
@@ -169,11 +182,14 @@
// we don't want to go to the children, not like they are
// any for this resource anyway.
return false;
+ } else if (AndroidConstants.FN_PROJECT_AIDL.equalsIgnoreCase(segments[1])) {
+ // need to force recompilation of all the aidl files
+ mFullAidlCompilation = true;
}
}
// at this point we can either be in the source folder or in the
- // resource foler or in a different folder that contains a source
+ // resource folder or in a different folder that contains a source
// folder.
// This is due to not all source folder being src/. Some could be
// something/somethingelse/src/
@@ -227,7 +243,8 @@
PreCompilerBuilder.PROPERTY_ANDROID_CONFLICT, true);
}
- // we add it anyway so that we can try to compile it every time.
+ // we add it anyway so that we can try to compile it at every compilation
+ // until the conflict is fixed.
mAidlToCompile.add(file);
} else {
@@ -245,6 +262,8 @@
boolean outputMessage = false;
+ // Special case of R.java/Manifest.java.
+ // FIXME: This does not check the package. Any modification of R.java/Manifest.java in another project will trigger a new recompilation of the resources.
if (AndroidConstants.FN_RESOURCE_CLASS.equals(fileName) ||
AndroidConstants.FN_MANIFEST_CLASS.equals(fileName)) {
// if it was removed, there's a possibility that it was removed due to a
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java
index 1de1438..1219aac 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java
@@ -62,13 +62,10 @@
switch (res) {
case ProjectHelper.COMPILER_COMPLIANCE_LEVEL:
errorMessage = Messages.Requires_Compiler_Compliance_5;
- return null;
case ProjectHelper.COMPILER_COMPLIANCE_SOURCE:
errorMessage = Messages.Requires_Source_Compatibility_5;
- return null;
case ProjectHelper.COMPILER_COMPLIANCE_CODEGEN_TARGET:
errorMessage = Messages.Requires_Class_Compatibility_5;
- return null;
}
if (errorMessage != null) {
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java
index 10be077..48ec7c3 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java
@@ -30,9 +30,9 @@
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.debug.launching.DeviceChooserDialog.DeviceChooserResponse;
import com.android.ide.eclipse.adt.debug.ui.EmulatorConfigTab;
-import com.android.ide.eclipse.adt.debug.ui.SkinRepository;
import com.android.ide.eclipse.adt.project.ProjectHelper;
import com.android.ide.eclipse.common.project.AndroidManifestHelper;
+import com.android.sdklib.SdkConstants;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
@@ -102,6 +102,9 @@
/** Debuggable attribute of the manifest file. */
Boolean mDebuggable = null;
+ /** Required ApiVersionNumber by the app. 0 means no requirements */
+ int mRequiredApiVersionNumber = 0;
+
InstallRetryMode mRetryMode = InstallRetryMode.NEVER;
/**
@@ -126,8 +129,8 @@
/** Basic constructor with activity and package info. */
public DelayedLaunchInfo(IProject project, String packageName, String activity,
- IFile pack, Boolean debuggable, int launchAction, AndroidLaunch launch,
- IProgressMonitor monitor) {
+ IFile pack, Boolean debuggable, int requiredApiVersionNumber, int launchAction,
+ AndroidLaunch launch, IProgressMonitor monitor) {
mProject = project;
mPackageName = packageName;
mActivity = activity;
@@ -136,6 +139,7 @@
mLaunch = launch;
mMonitor = monitor;
mDebuggable = debuggable;
+ mRequiredApiVersionNumber = requiredApiVersionNumber;
}
}
@@ -256,13 +260,10 @@
try {
mSkin = config.getAttribute(LaunchConfigDelegate.ATTR_SKIN, mSkin);
if (mSkin == null) {
- mSkin = SkinRepository.getInstance().checkSkin(
- LaunchConfigDelegate.DEFAULT_SKIN);
- } else {
- mSkin = SkinRepository.getInstance().checkSkin(mSkin);
+ mSkin = SdkConstants.SKIN_DEFAULT;
}
} catch (CoreException e) {
- mSkin = SkinRepository.getInstance().checkSkin(LaunchConfigDelegate.DEFAULT_SKIN);
+ mSkin = SdkConstants.SKIN_DEFAULT;
}
int index = LaunchConfigDelegate.DEFAULT_SPEED;
@@ -539,7 +540,7 @@
LaunchConfigDelegate.DEFAULT_DELAY);
// default skin
- wc.setAttribute(LaunchConfigDelegate.ATTR_SKIN, LaunchConfigDelegate.DEFAULT_SKIN);
+ wc.setAttribute(LaunchConfigDelegate.ATTR_SKIN, SdkConstants.SKIN_DEFAULT);
// default wipe data mode
wc.setAttribute(LaunchConfigDelegate.ATTR_WIPE_DATA,
@@ -599,13 +600,14 @@
* defined by <code>ILaunchManager</code> - <code>RUN_MODE</code> or
* <code>DEBUG_MODE</code>.
* @param apk the resource to the apk to launch.
- * @param debuggable
+ * @param debuggable the debuggable value of the app, or null if not set.
+ * @param requiredApiVersionNumber the api version required by the app, or -1 if none.
* @param activity the class to provide to am to launch
* @param config the launch configuration
* @param launch the launch object
*/
public void launch(final IProject project, String mode, IFile apk,
- String packageName, Boolean debuggable, String activity,
+ String packageName, Boolean debuggable, int requiredApiVersionNumber, String activity,
final AndroidLaunchConfiguration config, final AndroidLaunch launch,
IProgressMonitor monitor) {
@@ -619,7 +621,8 @@
// create the launch info
final DelayedLaunchInfo launchInfo = new DelayedLaunchInfo(project, packageName,
- activity, apk, debuggable, config.mLaunchAction, launch, monitor);
+ activity, apk, debuggable, requiredApiVersionNumber, config.mLaunchAction,
+ launch, monitor);
// set the debug mode
launchInfo.mDebugMode = mode.equals(ILaunchManager.DEBUG_MODE);
@@ -711,6 +714,7 @@
// stop the launch and return
mWaitingForEmulatorLaunches.remove(launchInfo);
+ AdtPlugin.printErrorToConsole(project, "Launch canceled!");
launch.stopLaunch();
return;
}
@@ -761,31 +765,63 @@
}
}
- private void checkBuildInfo(DelayedLaunchInfo launchInfo, Device device) {
+ /**
+ * Checks the build information, and returns whether the launch should continue.
+ * <p/>The value tested are:
+ * <ul>
+ * <li>Minimum API version requested by the application. If the target device does not match,
+ * the launch is canceled.</li>
+ * <li>Debuggable attribute of the application and whether or not the device requires it. If
+ * the device requires it and it is not set in the manifest, the launch will be forced to
+ * "release" mode instead of "debug"</li>
+ * <ul>
+ * @param launchInfo
+ * @param device
+ * @return
+ */
+ private boolean checkBuildInfo(DelayedLaunchInfo launchInfo, Device device) {
if (device != null) {
- // get the SDK build
- String sdkBuild = AdtPlugin.getSdkApiVersion();
-
- // can only complain if the sdkBuild is known
- if (sdkBuild != null) {
-
- String deviceVersion = device.getProperty(Device.PROP_BUILD_VERSION);
-
- if (deviceVersion == null) {
- AdtPlugin.printToConsole(launchInfo.mProject, "WARNING: Unknown device API version!");
- } else {
- if (sdkBuild.equals(deviceVersion) == false) {
- // TODO do a proper check, including testing the content of the uses-sdk string in the manifest to detect real incompatibility.
- String msg = String.format(
- "WARNING: Device API version (%1$s) does not match SDK API version (%2$s)",
- deviceVersion, sdkBuild);
- AdtPlugin.printErrorToConsole(launchInfo.mProject, msg);
- }
- }
- } else {
- AdtPlugin.printToConsole(launchInfo.mProject, "WARNING: Unknown SDK API version!");
+ // check the app required API level versus the target device API level
+
+ String deviceApiVersionName = device.getProperty(Device.PROP_BUILD_VERSION);
+ String value = device.getProperty(Device.PROP_BUILD_VERSION_NUMBER);
+ int deviceApiVersionNumber = 0;
+ try {
+ deviceApiVersionNumber = Integer.parseInt(value);
+ } catch (NumberFormatException e) {
+ // pass, we'll keep the deviceVersionNumber value at 0.
}
+ if (launchInfo.mRequiredApiVersionNumber == 0) {
+ // warn the API level requirement is not set.
+ AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ "WARNING: Application does not specify an API level requirement!");
+
+ // and display the target device API level (if known)
+ if (deviceApiVersionName == null || deviceApiVersionNumber == 0) {
+ AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ "WARNING: Unknown device API version!");
+ } else {
+ AdtPlugin.printErrorToConsole(launchInfo.mProject, String.format(
+ "Device API version is %1$d (Android %2$s)", deviceApiVersionNumber,
+ deviceApiVersionName));
+ }
+ } else { // app requires a specific API level
+ if (deviceApiVersionName == null || deviceApiVersionNumber == 0) {
+ AdtPlugin.printToConsole(launchInfo.mProject,
+ "WARNING: Unknown device API version!");
+ } else if (deviceApiVersionNumber < launchInfo.mRequiredApiVersionNumber) {
+ String msg = String.format(
+ "ERROR: Application requires API version %1$d. Device API version is %2$d (Android %3$s).",
+ launchInfo.mRequiredApiVersionNumber, deviceApiVersionNumber,
+ deviceApiVersionName);
+ AdtPlugin.printErrorToConsole(launchInfo.mProject, msg);
+
+ // abort the launch
+ return false;
+ }
+ }
+
// now checks that the device/app can be debugged (if needed)
if (device.isEmulator() == false && launchInfo.mDebugMode) {
String debuggableDevice = device.getProperty(Device.PROP_DEBUGGABLE);
@@ -818,6 +854,8 @@
}
}
}
+
+ return true;
}
/**
@@ -829,10 +867,16 @@
* @return true if succeed
*/
private boolean simpleLaunch(DelayedLaunchInfo launchInfo, Device device) {
- checkBuildInfo(launchInfo, device);
+ // API level check
+ if (checkBuildInfo(launchInfo, device) == false) {
+ AdtPlugin.printErrorToConsole(launchInfo.mProject, "Launch canceled!");
+ launchInfo.mLaunch.stopLaunch();
+ return false;
+ }
// sync the app
if (syncApp(launchInfo, device) == false) {
+ AdtPlugin.printErrorToConsole(launchInfo.mProject, "Launch canceled!");
launchInfo.mLaunch.stopLaunch();
return false;
}
@@ -1127,6 +1171,8 @@
} catch (IOException e) {
// something went wrong trying to launch the app.
// lets stop the Launch
+ AdtPlugin.printErrorToConsole(info.mProject,
+ String.format("Launch error: %s", e.getMessage()));
info.mLaunch.stopLaunch();
// and remove it from the list of app waiting for debuggers
@@ -1139,25 +1185,20 @@
private boolean launchEmulator(AndroidLaunchConfiguration config) {
// split the custom command line in segments
- String[] segs;
+ ArrayList<String> customArgs = new ArrayList<String>();
boolean has_wipe_data = false;
if (config.mEmulatorCommandLine != null && config.mEmulatorCommandLine.length() > 0) {
- segs = config.mEmulatorCommandLine.split("\\s+"); //$NON-NLS-1$
+ String[] segments = config.mEmulatorCommandLine.split("\\s+"); //$NON-NLS-1$
// we need to remove the empty strings
- ArrayList<String> array = new ArrayList<String>();
- for (String s : segs) {
+ for (String s : segments) {
if (s.length() > 0) {
- array.add(s);
+ customArgs.add(s);
if (!has_wipe_data && s.equals(FLAG_WIPE_DATA)) {
has_wipe_data = true;
}
}
}
-
- segs = array.toArray(new String[array.size()]);
- } else {
- segs = new String[0];
}
boolean needs_wipe_data = config.mWipeData && !has_wipe_data;
@@ -1167,29 +1208,37 @@
}
}
- boolean needs_no_boot_anim = config.mNoBootAnim;
+ // build the command line based on the available parameters.
+ ArrayList<String> list = new ArrayList<String>();
+
+ list.add(AdtPlugin.getOsAbsoluteEmulator());
+ if (config.mSkin != null) {
+ list.add(FLAG_SKIN);
+ list.add(config.mSkin);
+ }
- // get the command line
- String[] command = new String[7 + segs.length +
- (needs_wipe_data ? 1 : 0) +
- (needs_no_boot_anim ? 1 : 0)];
- int index = 0;
- command[index++] = AdtPlugin.getOsAbsoluteEmulator();
- command[index++] = FLAG_SKIN; //$NON-NLS-1$
- command[index++] = config.mSkin;
- command[index++] = FLAG_NETSPEED; //$NON-NLS-1$
- command[index++] = config.mNetworkSpeed;
- command[index++] = FLAG_NETDELAY; //$NON-NLS-1$
- command[index++] = config.mNetworkDelay;
+ if (config.mNetworkSpeed != null) {
+ list.add(FLAG_NETSPEED);
+ list.add(config.mNetworkSpeed);
+ }
+
+ if (config.mNetworkDelay != null) {
+ list.add(FLAG_NETDELAY);
+ list.add(config.mNetworkDelay);
+ }
+
if (needs_wipe_data) {
- command[index++] = FLAG_WIPE_DATA;
+ list.add(FLAG_WIPE_DATA);
}
- if (needs_no_boot_anim) {
- command[index++] = FLAG_NO_BOOT_ANIM;
+
+ if (config.mNoBootAnim) {
+ list.add(FLAG_NO_BOOT_ANIM);
}
- for (String s : segs) {
- command[index++] = s;
- }
+
+ list.addAll(customArgs);
+
+ // convert the list into an array for the call to exec.
+ String[] command = list.toArray(new String[list.size()]);
// launch the emulator
try {
@@ -1278,12 +1327,11 @@
/**
* Launch a new thread that connects a remote debugger on the specified port.
* @param debugPort The port to connect the debugger to
- * @param launch The associated AndroidLaunch object.
+ * @param androidLaunch The associated AndroidLaunch object.
* @param monitor A Progress monitor
* @see connectRemoveDebugger()
*/
- public static void launchRemoteDebugger(final ILaunchConfiguration config,
- final int debugPort, final AndroidLaunch androidLaunch,
+ public static void launchRemoteDebugger( final int debugPort, final AndroidLaunch androidLaunch,
final IProgressMonitor monitor) {
new Thread("Debugger connection") { //$NON-NLS-1$
@Override
@@ -1342,13 +1390,14 @@
synchronized (sListLock) {
// look if there's an app waiting for a device
if (mWaitingForEmulatorLaunches.size() > 0) {
- // remove first item from the list
+ // get/remove first launch item from the list
+ // FIXME: what if we have multiple launches waiting?
DelayedLaunchInfo launchInfo = mWaitingForEmulatorLaunches.get(0);
mWaitingForEmulatorLaunches.remove(0);
-
- // give it its device
+
+ // give the launch item its device for later use.
launchInfo.mDevice = device;
-
+
// and move it to the other list
mWaitingForReadyEmulatorList.add(launchInfo);
@@ -1433,12 +1482,23 @@
// look for application waiting for home
synchronized (sListLock) {
- boolean foundMatch = false;
for (int i = 0 ; i < mWaitingForReadyEmulatorList.size() ;) {
DelayedLaunchInfo launchInfo = mWaitingForReadyEmulatorList.get(i);
if (launchInfo.mDevice == device) {
// it's match, remove from the list
mWaitingForReadyEmulatorList.remove(i);
+
+ // We couldn't check earlier the API level of the device
+ // (it's asynchronous when the device boot, and usually
+ // deviceConnected is called before it's queried for its build info)
+ // so we check now
+ if (checkBuildInfo(launchInfo, device) == false) {
+ // device is not the proper API!
+ AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ "Launch canceled!");
+ launchInfo.mLaunch.stopLaunch();
+ return;
+ }
AdtPlugin.printToConsole(launchInfo.mProject,
String.format("HOME is up on device '%1$s'",
@@ -1448,16 +1508,14 @@
if (syncApp(launchInfo, device)) {
// application package is sync'ed, lets attempt to launch it.
launchApp(launchInfo, device);
-
- // if we haven't checked the device build info, lets do it here
- if (foundMatch == false) {
- foundMatch = true;
- checkBuildInfo(launchInfo, device);
- }
} else {
// failure! Cancel and return
+ AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ "Launch canceled!");
launchInfo.mLaunch.stopLaunch();
}
+
+ break;
} else {
i++;
}
@@ -1530,6 +1588,8 @@
}
} catch (CoreException e) {
// well something went wrong.
+ AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ String.format("Launch error: %s", e.getMessage()));
// stop the launch
launchInfo.mLaunch.stopLaunch();
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchConfigDelegate.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchConfigDelegate.java
index e5ccb2b..5d3e349 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchConfigDelegate.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchConfigDelegate.java
@@ -83,11 +83,6 @@
/** Skin to be used to launch the emulator */
public static final String ATTR_SKIN = AdtPlugin.PLUGIN_ID + ".skin"; //$NON-NLS-1$
- /**
- * Name of the default Skin.
- */
- public static final String DEFAULT_SKIN = "HVGA"; //$NON-NLS-1$
-
public static final String ATTR_SPEED = AdtPlugin.PLUGIN_ID + ".speed"; //$NON-NLS-1$
/**
@@ -138,8 +133,7 @@
// if we have a valid debug port, this means we're debugging an app
// that's already launched.
if (debugPort != INVALID_DEBUG_PORT) {
- AndroidLaunchController.launchRemoteDebugger(configuration,
- debugPort, androidLaunch, monitor);
+ AndroidLaunchController.launchRemoteDebugger(debugPort, androidLaunch, monitor);
return;
}
@@ -302,7 +296,8 @@
// everything seems fine, we ask the launch controller to handle
// the rest
controller.launch(project, mode, applicationPackage, manifestParser.getPackage(),
- manifestParser.getDebuggable(), activityName, config, androidLaunch, monitor);
+ manifestParser.getDebuggable(), manifestParser.getApiLevelRequirement(),
+ activityName, config, androidLaunch, monitor);
}
@Override
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/EmulatorConfigTab.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/EmulatorConfigTab.java
index 1d36add..c7b340c 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/EmulatorConfigTab.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/EmulatorConfigTab.java
@@ -18,13 +18,19 @@
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.debug.launching.LaunchConfigDelegate;
-import com.android.ide.eclipse.adt.debug.ui.SkinRepository.Skin;
+import com.android.ide.eclipse.adt.sdk.Sdk;
+import com.android.ide.eclipse.common.project.BaseProjectHelper;
import com.android.ide.eclipse.ddms.DdmsPlugin;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.SdkConstants;
+import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
@@ -82,6 +88,8 @@
private Button mNoBootAnimButton;
+ private IAndroidTarget mTarget;
+
/**
* Returns the emulator ready speed option value.
* @param value The index of the combo selection.
@@ -169,12 +177,6 @@
new Label(mEmulatorOptionsGroup, SWT.NONE).setText("Screen Size:");
mSkinCombo = new Combo(mEmulatorOptionsGroup, SWT.READ_ONLY);
- Skin[] skins = SkinRepository.getInstance().getSkins();
- if (skins != null) {
- for (Skin skin : skins) {
- mSkinCombo.add(skin.getDescription());
- }
- }
mSkinCombo.addSelectionListener(new SelectionAdapter() {
// called when selection changes
@Override
@@ -182,7 +184,6 @@
updateLaunchConfigurationDialog();
}
});
- mSkinCombo.pack();
// network options
new Label(mEmulatorOptionsGroup, SWT.NONE).setText("Network Speed:");
@@ -287,6 +288,42 @@
}
mAutoTargetButton.setSelection(value);
mManualTargetButton.setSelection(!value);
+
+ // look for the project name to get its target.
+ String projectName = "";
+ try {
+ projectName = configuration.getAttribute(
+ IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, projectName);
+ } catch (CoreException ce) {
+ }
+
+ IProject project = null;
+
+ // get the list of existing Android projects from the workspace.
+ IJavaProject[] projects = BaseProjectHelper.getAndroidProjects();
+ if (projects != null) {
+ // look for the project whose name we read from the configuration.
+ for (IJavaProject p : projects) {
+ if (p.getElementName().equals(projectName)) {
+ project = p.getProject();
+ break;
+ }
+ }
+ }
+
+ mSkinCombo.removeAll();
+ if (project != null) {
+ mTarget = Sdk.getCurrent().getTarget(project);
+ if (mTarget != null) {
+ String[] skins = mTarget.getSkins();
+ if (skins != null) {
+ for (String skin : skins) {
+ mSkinCombo.add(skin);
+ }
+ mSkinCombo.pack();
+ }
+ }
+ }
value = LaunchConfigDelegate.DEFAULT_WIPE_DATA;
try {
@@ -307,16 +344,18 @@
int index = -1;
try {
String skin = configuration.getAttribute(LaunchConfigDelegate.ATTR_SKIN, (String)null);
- if (skin != null) {
- index = getSkinIndex(skin);
+ if (skin == null) {
+ skin = SdkConstants.SKIN_DEFAULT;
}
+
+ index = getSkinIndex(skin);
} catch (CoreException e) {
- index = getSkinIndex(SkinRepository.getInstance().checkSkin(
- LaunchConfigDelegate.DEFAULT_SKIN));
+ index = getSkinIndex(SdkConstants.SKIN_DEFAULT);
}
if (index == -1) {
- mSkinCombo.clearSelection();
+ mSkinCombo.select(0);
+ updateLaunchConfigurationDialog();
} else {
mSkinCombo.select(index);
}
@@ -387,7 +426,7 @@
configuration.setAttribute(LaunchConfigDelegate.ATTR_TARGET_MODE,
LaunchConfigDelegate.DEFAULT_TARGET_MODE);
configuration.setAttribute(LaunchConfigDelegate.ATTR_SKIN,
- LaunchConfigDelegate.DEFAULT_SKIN);
+ SdkConstants.SKIN_DEFAULT);
configuration.setAttribute(LaunchConfigDelegate.ATTR_SPEED,
LaunchConfigDelegate.DEFAULT_SPEED);
configuration.setAttribute(LaunchConfigDelegate.ATTR_DELAY,
@@ -403,11 +442,31 @@
}
private String getSkinNameByIndex(int index) {
- return SkinRepository.getInstance().getSkinNameByIndex(index);
+ if (mTarget != null && index > 0) {
+ String[] skins = mTarget.getSkins();
+ if (skins != null && index < skins.length) {
+ return skins[index];
+ }
+ }
+
+ return null;
}
private int getSkinIndex(String name) {
- return SkinRepository.getInstance().getSkinIndex(name);
+ if (mTarget != null) {
+ String[] skins = mTarget.getSkins();
+ if (skins != null) {
+ int index = 0;
+ for (String skin : skins) {
+ if (skin.equalsIgnoreCase(name)) {
+ return index;
+ }
+ index++;
+ }
+ }
+ }
+
+ return -1;
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/SkinRepository.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/SkinRepository.java
deleted file mode 100644
index a813026..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/SkinRepository.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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.ide.eclipse.adt.debug.ui;
-
-import com.android.ide.eclipse.common.AndroidConstants;
-
-import java.io.File;
-import java.util.ArrayList;
-
-/**
- * Repository for the emulator skins. This class is responsible for parsing the skin folder.
- */
-public class SkinRepository {
-
- private final static SkinRepository sInstance = new SkinRepository();
-
- private Skin[] mSkins;
-
- public static class Skin {
-
- String mName;
-
- public Skin(String name) {
- mName = name;
- }
-
- public String getName() {
- return mName;
- }
-
- /**
- * Returns the human readable description of the skin.
- */
- public String getDescription() {
- // TODO: parse the skin and output the description.
- return mName;
- }
- }
-
- /**
- * Returns the singleton instance.
- */
- public static SkinRepository getInstance() {
- return sInstance;
- }
-
- /**
- * Parse the skin folder and build the skin list.
- * @param osPath The path of the skin folder.
- */
- public void parseFolder(String osPath) {
- File skinFolder = new File(osPath);
-
- if (skinFolder.isDirectory()) {
- ArrayList<Skin> skinList = new ArrayList<Skin>();
-
- File[] files = skinFolder.listFiles();
-
- for (File skin : files) {
- if (skin.isDirectory()) {
- // check for layout file
- File layout = new File(skin.getPath() + File.separator
- + AndroidConstants.FN_LAYOUT);
-
- if (layout.isFile()) {
- // for now we don't parse the content of the layout and
- // simply add the directory to the list.
- skinList.add(new Skin(skin.getName()));
- }
- }
- }
-
- mSkins = skinList.toArray(new Skin[skinList.size()]);
- } else {
- mSkins = new Skin[0];
- }
- }
-
- public Skin[] getSkins() {
- return mSkins;
- }
-
- /**
- * Returns a valid skin folder name. If <code>skin</code> is valid, then it is returned,
- * otherwise the first valid skin name is returned.
- * @param skin the Skin name to check
- * @return a valid skin name or null if there aren't any.
- */
- public String checkSkin(String skin) {
- if (mSkins != null) {
- for (Skin s : mSkins) {
- if (s.getName().equals(skin)) {
- return skin;
- }
- }
-
- if (mSkins.length > 0) {
- return mSkins[0].getName();
- }
- }
-
- return null;
- }
-
-
- /**
- * Returns the name of a skin by index.
- * @param index The index of the skin to return
- * @return the skin name of null if the index is invalid.
- */
- public String getSkinNameByIndex(int index) {
- if (mSkins != null) {
- if (index >= 0 && index < mSkins.length) {
- return mSkins[index].getName();
- }
- }
- return null;
- }
-
- /**
- * Returns the index (0 based) of the skin matching the name.
- * @param name The name of the skin to look for.
- * @return the index of the skin or -1 if the skin was not found.
- */
- public int getSkinIndex(String name) {
- if (mSkins != null) {
- int count = mSkins.length;
- for (int i = 0 ; i < count ; i++) {
- Skin s = mSkins[i];
- if (s.mName.equals(name)) {
- return i;
- }
- }
- }
-
- return -1;
- }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/editors/java/ReadOnlyJavaEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/editors/java/ReadOnlyJavaEditor.java
deleted file mode 100644
index 1c9a569..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/editors/java/ReadOnlyJavaEditor.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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.ide.eclipse.adt.editors.java;
-
-import org.eclipse.jdt.ui.PreferenceConstants;
-import org.eclipse.jdt.ui.text.IJavaPartitions;
-import org.eclipse.jdt.ui.text.JavaSourceViewerConfiguration;
-import org.eclipse.jdt.ui.text.JavaTextTools;
-import org.eclipse.jface.preference.IPreferenceStore;
-import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor;
-
-/**
- * Read only java editors. This looks like the regular Java editor, except that it
- * prevents editing the files. This is used for automatically generated java classes.
- */
-public class ReadOnlyJavaEditor extends AbstractDecoratedTextEditor {
-
- public final static String ID =
- "com.android.ide.eclipse.adt.editors.java.ReadOnlyJavaEditor"; //$NON-NLS-1$
-
- public ReadOnlyJavaEditor() {
- IPreferenceStore javaUiStore = PreferenceConstants.getPreferenceStore();
- JavaTextTools jtt = new JavaTextTools(javaUiStore);
-
- JavaSourceViewerConfiguration jsvc = new JavaSourceViewerConfiguration(
- jtt.getColorManager(), javaUiStore, this, IJavaPartitions.JAVA_PARTITIONING);
-
- setSourceViewerConfiguration(jsvc);
- }
-
- @Override
- public boolean isEditable() {
- return false;
- }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/preferences/BuildPreferencePage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/preferences/BuildPreferencePage.java
index 136c0f3..434269c 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/preferences/BuildPreferencePage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/preferences/BuildPreferencePage.java
@@ -18,6 +18,9 @@
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.jarutils.DebugKeyProvider;
+import com.android.jarutils.DebugKeyProvider.KeytoolException;
+import com.android.prefs.AndroidLocation.AndroidLocationException;
import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
@@ -29,6 +32,13 @@
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
+import java.io.File;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+
/**
* Preference page for build options.
*
@@ -75,7 +85,7 @@
addField(new ReadOnlyFieldEditor(AdtPlugin.PREFS_DEFAULT_DEBUG_KEYSTORE,
Messages.BuildPreferencePage_Default_KeyStore, getFieldEditorParent()));
- addField(new FileFieldEditor(AdtPlugin.PREFS_CUSTOM_DEBUG_KEYSTORE,
+ addField(new KeystoreFieldEditor(AdtPlugin.PREFS_CUSTOM_DEBUG_KEYSTORE,
Messages.BuildPreferencePage_Custom_Keystore, getFieldEditorParent()));
}
@@ -105,4 +115,103 @@
control.setEditable(false);
}
}
+
+ /**
+ * Custom {@link FileFieldEditor} that checks that the keystore is valid.
+ */
+ private static class KeystoreFieldEditor extends FileFieldEditor {
+ public KeystoreFieldEditor(String name, String label, Composite parent) {
+ super(name, label, parent);
+ setValidateStrategy(VALIDATE_ON_KEY_STROKE);
+ }
+
+ @Override
+ protected boolean checkState() {
+ String fileName = getTextControl().getText();
+ fileName = fileName.trim();
+
+ // empty values are considered ok.
+ if (fileName.length() > 0) {
+ File file = new File(fileName);
+ if (file.isFile()) {
+ // attempt to load the debug key.
+ try {
+ DebugKeyProvider provider = new DebugKeyProvider(fileName,
+ null /* storeType */, null /* key gen output */);
+ PrivateKey key = provider.getDebugKey();
+ X509Certificate certificate = (X509Certificate)provider.getCertificate();
+
+ if (key == null || certificate == null) {
+ showErrorMessage("Unable to find debug key in keystore!");
+ return false;
+ }
+
+ Date today = new Date();
+ if (certificate.getNotAfter().compareTo(today) < 0) {
+ showErrorMessage("Certificate is expired!");
+ return false;
+ }
+
+ if (certificate.getNotBefore().compareTo(today) > 0) {
+ showErrorMessage("Certificate validity is in the future!");
+ return false;
+ }
+
+ // we're good!
+ clearErrorMessage();
+ return true;
+ } catch (GeneralSecurityException e) {
+ handleException(e);
+ return false;
+ } catch (IOException e) {
+ handleException(e);
+ return false;
+ } catch (KeytoolException e) {
+ handleException(e);
+ return false;
+ } catch (AndroidLocationException e) {
+ handleException(e);
+ return false;
+ }
+
+
+ } else {
+ // file does not exist.
+ showErrorMessage("Not a valid keystore path.");
+ return false; // Apply/OK must be disabled
+ }
+ }
+
+ clearErrorMessage();
+ return true;
+ }
+
+ @Override
+ public Text getTextControl(Composite parent) {
+ setValidateStrategy(VALIDATE_ON_KEY_STROKE);
+ return super.getTextControl(parent);
+ }
+
+ /**
+ * Set the error message from a {@link Throwable}. If the exception has no message, try
+ * to get the message from the cause.
+ * @param t the Throwable.
+ */
+ private void handleException(Throwable t) {
+ String msg = t.getMessage();
+ if (t == null) {
+ Throwable cause = t.getCause();
+ if (cause != null) {
+ handleException(cause);
+ } else {
+ setErrorMessage("Uknown error when getting the debug key!");
+ }
+
+ return;
+ }
+
+ // valid text, display it.
+ showErrorMessage(msg);
+ }
+ }
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/CreateAidlImportAction.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/CreateAidlImportAction.java
index efbbf94..a1b3c38 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/CreateAidlImportAction.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/CreateAidlImportAction.java
@@ -17,6 +17,7 @@
package com.android.ide.eclipse.adt.project;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.common.AndroidConstants;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
@@ -117,7 +118,7 @@
// create the file with the parcelables
if (parcelables.size() > 0) {
IPath path = project.getLocation();
- path = path.append("/project.aidl"); //$NON-NLS-1$
+ path = path.append(AndroidConstants.FN_PROJECT_AIDL);
File f = new File(path.toOSString());
if (f.exists() == false) {
@@ -194,7 +195,7 @@
IType[] superInterfaces = typeHierarchy.getAllSuperInterfaces(type);
for (IType superInterface : superInterfaces) {
- if ("android.os.Parcelable".equals(superInterface.getFullyQualifiedName())) { //$NON-NLS-1$
+ if (AndroidConstants.CLASS_PARCELABLE.equals(superInterface.getFullyQualifiedName())) {
parcelables.add(type.getFullyQualifiedName());
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FolderDecorator.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FolderDecorator.java
new file mode 100644
index 0000000..1ca89cd
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FolderDecorator.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.adt.project;
+
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.common.AndroidConstants;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.IDecoration;
+import org.eclipse.jface.viewers.ILabelDecorator;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ILightweightLabelDecorator;
+
+/**
+ * A {@link ILabelDecorator} associated with an org.eclipse.ui.decorators extension.
+ * This is used to add android icons in some special folders in the package explorer.
+ */
+public class FolderDecorator implements ILightweightLabelDecorator {
+
+ private ImageDescriptor mDescriptor;
+
+ public FolderDecorator() {
+ mDescriptor = AdtPlugin.getImageDescriptor("/icons/android_project.png");
+ }
+
+ public void decorate(Object element, IDecoration decoration) {
+ if (element instanceof IFolder) {
+ IFolder folder = (IFolder)element;
+
+ // get the project and make sure this is an android project
+ IProject project = folder.getProject();
+
+ try {
+ if (project.hasNature(AndroidConstants.NATURE)) {
+ // check the folder is directly under the project.
+ if (folder.getParent().getType() == IResource.PROJECT) {
+ String name = folder.getName();
+ if (name.equals(AndroidConstants.FD_ASSETS)) {
+ decorate(decoration, " [Android assets]");
+ decoration.addOverlay(mDescriptor, IDecoration.TOP_RIGHT);
+ } else if (name.equals(AndroidConstants.FD_RESOURCES)) {
+ decorate(decoration, " [Android resources]");
+ decoration.addOverlay(mDescriptor, IDecoration.TOP_RIGHT);
+ } else if (name.equals(AndroidConstants.FD_NATIVE_LIBS)) {
+ decorate(decoration, " [Native Libraries]");
+ }
+ }
+ }
+ } catch (CoreException e) {
+ // log the error
+ AdtPlugin.log(e, "Unable to get nature of project '%s'.", project.getName());
+ }
+ }
+ }
+
+ public void decorate(IDecoration decoration, String suffix) {
+ decoration.addOverlay(mDescriptor, IDecoration.TOP_RIGHT);
+
+ // this is broken as it changes the color of the whole text, not only of the decoration.
+ // TODO: figure out how to change the color of the decoration only.
+// decoration.addSuffix(suffix);
+// ITheme theme = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme();
+// ColorRegistry registry = theme.getColorRegistry();
+// decoration.setForegroundColor(registry.get("org.eclipse.jdt.ui.ColoredLabels.decorations"));
+
+ }
+
+ public boolean isLabelProperty(Object element, String property) {
+ // at this time return false.
+ return false;
+ }
+
+ public void addListener(ILabelProviderListener listener) {
+ // No state change will affect the rendering.
+ }
+
+
+
+ public void removeListener(ILabelProviderListener listener) {
+ // No state change will affect the rendering.
+ }
+
+ public void dispose() {
+ // nothind to dispose
+ }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/NewXmlFileWizardAction.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/NewXmlFileWizardAction.java
new file mode 100644
index 0000000..c117b4e
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/NewXmlFileWizardAction.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.adt.project;
+
+import com.android.ide.eclipse.editors.wizards.NewXmlFileWizard;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPart;
+
+public class NewXmlFileWizardAction implements IObjectActionDelegate {
+
+ private ISelection mSelection;
+ private IWorkbench mWorkbench;
+
+ /**
+ * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
+ */
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+ mWorkbench = targetPart.getSite().getWorkbenchWindow().getWorkbench();
+ }
+
+ public void run(IAction action) {
+ if (mSelection instanceof IStructuredSelection) {
+ IStructuredSelection selection = (IStructuredSelection)mSelection;
+
+ // call the new xml file wizard on the current selection.
+ NewXmlFileWizard wizard = new NewXmlFileWizard();
+ wizard.init(mWorkbench, selection);
+ WizardDialog dialog = new WizardDialog(mWorkbench.getDisplay().getActiveShell(),
+ wizard);
+ dialog.open();
+ }
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ this.mSelection = selection;
+ }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java
index 24132b6..8678923 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java
@@ -33,7 +33,6 @@
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.QualifiedName;
-import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
@@ -178,31 +177,6 @@
}
/**
- * Check the validity of the javadoc attributes in a classpath entry.
- * @param frameworkEntry the classpath entry to check.
- * @return true if the javadoc attributes is valid, false otherwise.
- */
- public static boolean checkJavaDocPath(IClasspathEntry frameworkEntry) {
- // get the list of extra attributes
- IClasspathAttribute[] attributes = frameworkEntry.getExtraAttributes();
-
- // and search for the one about the javadoc
- for (IClasspathAttribute att : attributes) {
- if (IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME.
- equals(att.getName())) {
- // we found a javadoc attribute. Now we test its value.
- // get the expect value
- String validJavaDoc = getJavaDocPath(AdtPlugin.getOsAbsoluteFramework());
-
- // now compare and return
- return validJavaDoc.equals(att.getValue());
- }
- }
-
- return false;
- }
-
- /**
* Fix the project. This checks the SDK location.
* @param project The project to fix.
* @throws JavaModelException
@@ -264,14 +238,7 @@
continue;
}
} else if (kind == IClasspathEntry.CPE_CONTAINER) {
- IPath containerPath = entry.getPath();
-
- if (AndroidClasspathContainerInitializer.checkOldPath(containerPath)) {
- entries = ProjectHelper.removeEntryFromClasspath(entries, i);
-
- // continue, to skip the i++;
- continue;
- } else if (AndroidClasspathContainerInitializer.checkPath(containerPath)) {
+ if (AndroidClasspathContainerInitializer.checkPath(entry.getPath())) {
foundContainer = true;
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ExportWizard.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ExportWizard.java
index 1f51d09..de4b339 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ExportWizard.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ExportWizard.java
@@ -18,7 +18,10 @@
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.jarutils.KeystoreHelper;
import com.android.jarutils.SignedJarBuilder;
+import com.android.jarutils.DebugKeyProvider.IKeyGenOutput;
+import com.android.jarutils.DebugKeyProvider.KeytoolException;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
@@ -27,28 +30,38 @@
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IExportWizard;
import org.eclipse.ui.IWorkbench;
+import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
+import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
+import java.security.KeyStore.PrivateKeyEntry;
import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
/**
* Export wizard to export an apk signed with a release key/certificate.
*/
-public class ExportWizard extends Wizard implements IExportWizard {
+public final class ExportWizard extends Wizard implements IExportWizard {
private static final String PROJECT_LOGO_LARGE = "icons/android_large.png"; //$NON-NLS-1$
- private static final String PAGE_PRE = "preExportPage"; //$NON-NLS-1$
- private static final String PAGE_SIGNING = "signingExportPage"; //$NON-NLS-1$
- private static final String PAGE_FINAL = "finalExportPage"; //$NON-NLS-1$
+ private static final String PAGE_PROJECT_CHECK = "Page_ProjectCheck"; //$NON-NLS-1$
+ private static final String PAGE_KEYSTORE_SELECTION = "Page_KeystoreSelection"; //$NON-NLS-1$
+ private static final String PAGE_KEY_CREATION = "Page_KeyCreation"; //$NON-NLS-1$
+ private static final String PAGE_KEY_SELECTION = "Page_KeySelection"; //$NON-NLS-1$
+ private static final String PAGE_KEY_CHECK = "Page_KeyCheck"; //$NON-NLS-1$
static final String PROPERTY_KEYSTORE = "keystore"; //$NON-NLS-1$
static final String PROPERTY_ALIAS = "alias"; //$NON-NLS-1$
@@ -59,7 +72,41 @@
*/
static abstract class ExportWizardPage extends WizardPage {
- protected boolean mNewProjectReference = true;
+ /** bit mask constant for project data change event */
+ protected static final int DATA_PROJECT = 0x001;
+ /** bit mask constant for keystore data change event */
+ protected static final int DATA_KEYSTORE = 0x002;
+ /** bit mask constant for key data change event */
+ protected static final int DATA_KEY = 0x004;
+
+ protected static final VerifyListener sPasswordVerifier = new VerifyListener() {
+ public void verifyText(VerifyEvent e) {
+ // verify the characters are valid for password.
+ int len = e.text.length();
+
+ // first limit to 127 characters max
+ if (len + ((Text)e.getSource()).getText().length() > 127) {
+ e.doit = false;
+ return;
+ }
+
+ // now only take non control characters
+ for (int i = 0 ; i < len ; i++) {
+ if (e.text.charAt(i) < 32) {
+ e.doit = false;
+ return;
+ }
+ }
+ }
+ };
+
+ /**
+ * Bit mask indicating what changed while the page was hidden.
+ * @see #DATA_PROJECT
+ * @see #DATA_KEYSTORE
+ * @see #DATA_KEY
+ */
+ protected int mProjectDataChanged = 0;
ExportWizardPage(String name) {
super(name);
@@ -72,23 +119,38 @@
super.setVisible(visible);
if (visible) {
onShow();
- mNewProjectReference = false;
+ mProjectDataChanged = 0;
}
}
- void newProjectReference() {
- mNewProjectReference = true;
+ final void projectDataChanged(int changeMask) {
+ mProjectDataChanged |= changeMask;
+ }
+
+ /**
+ * Calls {@link #setErrorMessage(String)} and {@link #setPageComplete(boolean)} based on a
+ * {@link Throwable} object.
+ */
+ protected final void onException(Throwable t) {
+ String message = getExceptionMessage(t);
+
+ setErrorMessage(message);
+ setPageComplete(false);
}
}
- private ExportWizardPage mPages[] = new ExportWizardPage[3];
+ private ExportWizardPage mPages[] = new ExportWizardPage[5];
private IProject mProject;
private String mKeystore;
+ private String mKeystorePassword;
+ private boolean mKeystoreCreationMode;
+
private String mKeyAlias;
- private char[] mKeystorePassword;
- private char[] mKeyPassword;
+ private String mKeyPassword;
+ private int mValidity;
+ private String mDName;
private PrivateKey mPrivateKey;
private X509Certificate mCertificate;
@@ -97,6 +159,15 @@
private String mApkFilePath;
private String mApkFileName;
+ private ExportWizardPage mKeystoreSelectionPage;
+ private ExportWizardPage mKeyCreationPage;
+ private ExportWizardPage mKeySelectionPage;
+ private ExportWizardPage mKeyCheckPage;
+
+ private boolean mKeyCreationMode;
+
+ private List<String> mExistingAliases;
+
public ExportWizard() {
setHelpAvailable(false); // TODO have help
setWindowTitle("Export Android Application");
@@ -105,46 +176,101 @@
@Override
public void addPages() {
- addPage(mPages[0] = new PreExportPage(this, PAGE_PRE));
- addPage(mPages[1] = new SigningExportPage(this, PAGE_SIGNING));
- addPage(mPages[2] = new FinalExportPage(this, PAGE_FINAL));
+ addPage(mPages[0] = new ProjectCheckPage(this, PAGE_PROJECT_CHECK));
+ addPage(mKeystoreSelectionPage = mPages[1] = new KeystoreSelectionPage(this,
+ PAGE_KEYSTORE_SELECTION));
+ addPage(mKeyCreationPage = mPages[2] = new KeyCreationPage(this, PAGE_KEY_CREATION));
+ addPage(mKeySelectionPage = mPages[3] = new KeySelectionPage(this, PAGE_KEY_SELECTION));
+ addPage(mKeyCheckPage = mPages[4] = new KeyCheckPage(this, PAGE_KEY_CHECK));
}
@Override
public boolean performFinish() {
+ // first we make sure export is fine if the destination file already exists
+ File f = new File(mDestinationPath);
+ if (f.isFile()) {
+ if (AdtPlugin.displayPrompt("Export Wizard",
+ "File already exists. Do you want to overwrite it?") == false) {
+ return false;
+ }
+ }
+
// save the properties
ProjectHelper.saveStringProperty(mProject, PROPERTY_KEYSTORE, mKeystore);
ProjectHelper.saveStringProperty(mProject, PROPERTY_ALIAS, mKeyAlias);
ProjectHelper.saveStringProperty(mProject, PROPERTY_DESTINATION, mDestinationPath);
try {
- FileOutputStream fos = new FileOutputStream(mDestinationPath);
- SignedJarBuilder builder = new SignedJarBuilder(fos, mPrivateKey, mCertificate);
-
- // get the input file.
- FileInputStream fis = new FileInputStream(mApkFilePath);
- try {
- builder.writeZip(fis, null /* filter */);
- } finally {
+ if (mKeystoreCreationMode || mKeyCreationMode) {
+ final ArrayList<String> output = new ArrayList<String>();
+ if (KeystoreHelper.createNewStore(
+ mKeystore,
+ null /*storeType*/,
+ mKeystorePassword,
+ mKeyAlias,
+ mKeyPassword,
+ mDName,
+ mValidity,
+ new IKeyGenOutput() {
+ public void err(String message) {
+ output.add(message);
+ }
+ public void out(String message) {
+ output.add(message);
+ }
+ }) == false) {
+ // keystore creation error!
+ displayError(output.toArray(new String[output.size()]));
+ return false;
+ }
+
+ // keystore is created, now load the private key and certificate.
+ KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ FileInputStream fis = new FileInputStream(mKeystore);
+ keyStore.load(fis, mKeystorePassword.toCharArray());
fis.close();
+ PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(
+ mKeyAlias, new KeyStore.PasswordProtection(mKeyPassword.toCharArray()));
+
+ if (entry != null) {
+ mPrivateKey = entry.getPrivateKey();
+ mCertificate = (X509Certificate)entry.getCertificate();
+ } else {
+ // this really shouldn't happen since we now let the user choose the key
+ // from a list read from the store.
+ displayError("Could not find key");
+ return false;
+ }
}
-
- builder.close();
- fos.close();
- return true;
+ // check the private key/certificate again since it may have been created just above.
+ if (mPrivateKey != null && mCertificate != null) {
+ FileOutputStream fos = new FileOutputStream(mDestinationPath);
+ SignedJarBuilder builder = new SignedJarBuilder(fos, mPrivateKey, mCertificate);
+
+ // get the input file.
+ FileInputStream fis = new FileInputStream(mApkFilePath);
+ try {
+ builder.writeZip(fis, null /* filter */);
+ } finally {
+ fis.close();
+ }
+
+ builder.close();
+ fos.close();
+
+ return true;
+ }
} catch (FileNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ displayError(e);
} catch (NoSuchAlgorithmException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ displayError(e);
} catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ displayError(e);
} catch (GeneralSecurityException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ displayError(e);
+ } catch (KeytoolException e) {
+ displayError(e);
}
return false;
@@ -152,8 +278,13 @@
@Override
public boolean canFinish() {
+ // check if we have the apk to resign, the destination location, and either
+ // a private key/certificate or the creation mode. In creation mode, unless
+ // all the key/keystore info is valid, the user cannot reach the last page, so there's
+ // no need to check them again here.
return mApkFilePath != null &&
- mPrivateKey != null && mCertificate != null &&
+ ((mPrivateKey != null && mCertificate != null)
+ || mKeystoreCreationMode || mKeyCreationMode) &&
mDestinationPath != null;
}
@@ -175,6 +306,22 @@
}
}
+ ExportWizardPage getKeystoreSelectionPage() {
+ return mKeystoreSelectionPage;
+ }
+
+ ExportWizardPage getKeyCreationPage() {
+ return mKeyCreationPage;
+ }
+
+ ExportWizardPage getKeySelectionPage() {
+ return mKeySelectionPage;
+ }
+
+ ExportWizardPage getKeyCheckPage() {
+ return mKeyCheckPage;
+ }
+
/**
* Returns an image descriptor for the wizard logo.
*/
@@ -192,10 +339,7 @@
mApkFilePath = apkFilePath;
mApkFileName = filename;
- // indicate to the page that the project was changed.
- for (ExportWizardPage page : mPages) {
- page.newProjectReference();
- }
+ updatePageOnChange(ExportWizardPage.DATA_PROJECT);
}
String getApkFilename() {
@@ -206,42 +350,95 @@
mKeystore = path;
mPrivateKey = null;
mCertificate = null;
+
+ updatePageOnChange(ExportWizardPage.DATA_KEYSTORE);
}
String getKeystore() {
return mKeystore;
}
+ void setKeystoreCreationMode(boolean createStore) {
+ mKeystoreCreationMode = createStore;
+ updatePageOnChange(ExportWizardPage.DATA_KEYSTORE);
+ }
+
+ boolean getKeystoreCreationMode() {
+ return mKeystoreCreationMode;
+ }
+
+
+ void setKeystorePassword(String password) {
+ mKeystorePassword = password;
+ mPrivateKey = null;
+ mCertificate = null;
+
+ updatePageOnChange(ExportWizardPage.DATA_KEYSTORE);
+ }
+
+ String getKeystorePassword() {
+ return mKeystorePassword;
+ }
+
+ void setKeyCreationMode(boolean createKey) {
+ mKeyCreationMode = createKey;
+ updatePageOnChange(ExportWizardPage.DATA_KEY);
+ }
+
+ boolean getKeyCreationMode() {
+ return mKeyCreationMode;
+ }
+
+ void setExistingAliases(List<String> aliases) {
+ mExistingAliases = aliases;
+ }
+
+ List<String> getExistingAliases() {
+ return mExistingAliases;
+ }
+
void setKeyAlias(String name) {
mKeyAlias = name;
mPrivateKey = null;
mCertificate = null;
+
+ updatePageOnChange(ExportWizardPage.DATA_KEY);
}
String getKeyAlias() {
return mKeyAlias;
}
-
- void setKeystorePassword(char[] password) {
- mKeystorePassword = password;
- mPrivateKey = null;
- mCertificate = null;
- }
-
- char[] getKeystorePassword() {
- return mKeystorePassword;
- }
-
- void setKeyPassword(char[] password) {
+
+ void setKeyPassword(String password) {
mKeyPassword = password;
mPrivateKey = null;
mCertificate = null;
+
+ updatePageOnChange(ExportWizardPage.DATA_KEY);
}
- char[] getKeyPassword() {
+ String getKeyPassword() {
return mKeyPassword;
}
+ void setValidity(int validity) {
+ mValidity = validity;
+ updatePageOnChange(ExportWizardPage.DATA_KEY);
+ }
+
+ int getValidity() {
+ return mValidity;
+ }
+
+ void setDName(String dName) {
+ mDName = dName;
+ updatePageOnChange(ExportWizardPage.DATA_KEY);
+ }
+
+ String getDName() {
+ return mDName;
+ }
+
void setSigningInfo(PrivateKey privateKey, X509Certificate certificate) {
mPrivateKey = privateKey;
mCertificate = certificate;
@@ -251,4 +448,54 @@
mDestinationPath = path;
}
+ void updatePageOnChange(int changeMask) {
+ for (ExportWizardPage page : mPages) {
+ page.projectDataChanged(changeMask);
+ }
+ }
+
+ private void displayError(String... messages) {
+ String message = null;
+ if (messages.length == 1) {
+ message = messages[0];
+ } else {
+ StringBuilder sb = new StringBuilder(messages[0]);
+ for (int i = 1; i < messages.length; i++) {
+ sb.append('\n');
+ sb.append(messages[i]);
+ }
+
+ message = sb.toString();
+ }
+
+ AdtPlugin.displayError("Export Wizard", message);
+ }
+
+ private void displayError(Exception e) {
+ String message = getExceptionMessage(e);
+ displayError(message);
+
+ AdtPlugin.log(e, "Export Wizard Error");
+ }
+
+ /**
+ * Returns the {@link Throwable#getMessage()}. If the {@link Throwable#getMessage()} returns
+ * <code>null</code>, the method is called again on the cause of the Throwable object.
+ * <p/>If no Throwable in the chain has a valid message, the canonical name of the first
+ * exception is returned.
+ */
+ private static String getExceptionMessage(Throwable t) {
+ String message = t.getMessage();
+ if (message == null) {
+ Throwable cause = t.getCause();
+ if (cause != null) {
+ return getExceptionMessage(cause);
+ }
+
+ // no more cause and still no message. display the first exception.
+ return cause.getClass().getCanonicalName();
+ }
+
+ return message;
+ }
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/FinalExportPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/FinalExportPage.java
deleted file mode 100644
index 206e3aa..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/FinalExportPage.java
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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.ide.eclipse.adt.project.export;
-
-import com.android.ide.eclipse.adt.project.ProjectHelper;
-import com.android.ide.eclipse.adt.project.export.ExportWizard.ExportWizardPage;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.FileDialog;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.forms.widgets.FormText;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.UnrecoverableEntryException;
-import java.security.KeyStore.PrivateKeyEntry;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.util.Calendar;
-
-public class FinalExportPage extends ExportWizardPage {
-
- private final ExportWizard mWizard;
- private PrivateKey mPrivateKey;
- private X509Certificate mCertificate;
- private Text mDestination;
- private Button mBrowseButton;
- private boolean mFatalSigningError;
- private FormText mDetailText;
-
- protected FinalExportPage(ExportWizard wizard, String pageName) {
- super(pageName);
- mWizard = wizard;
-
- setTitle("Application Export");
- setDescription("Export the signed Application package.");
- }
-
- public void createControl(Composite parent) {
- setErrorMessage(null);
- setMessage(null);
-
- // build the ui.
- Composite composite = new Composite(parent, SWT.NULL);
- composite.setLayoutData(new GridData(GridData.FILL_BOTH));
- GridLayout gl = new GridLayout(3, false);
- gl.verticalSpacing *= 3;
- composite.setLayout(gl);
-
- GridData gd;
-
- new Label(composite, SWT.NONE).setText("Destination APK file:");
- mDestination = new Text(composite, SWT.BORDER);
- mDestination.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
- mDestination.addModifyListener(new ModifyListener() {
- public void modifyText(ModifyEvent e) {
- onDestinationChange();
- }
- });
- mBrowseButton = new Button(composite, SWT.PUSH);
- mBrowseButton.setText("Browse...");
- mBrowseButton.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- FileDialog fileDialog = new FileDialog(mBrowseButton.getShell(), SWT.SAVE);
-
- fileDialog.setText("Destination file name");
- fileDialog.setFileName(mWizard.getApkFilename());
-
- String saveLocation = fileDialog.open();
- if (saveLocation != null) {
- mDestination.setText(saveLocation);
- }
- }
- });
-
- mDetailText = new FormText(composite, SWT.NONE);
- mDetailText.setLayoutData(gd = new GridData(GridData.FILL_BOTH));
- gd.horizontalSpan = 3;
-
- setControl(composite);
- }
-
- @Override
- void onShow() {
- // fill the texts with information loaded from the project.
- if (mNewProjectReference) {
- // reset the destination from the content of the project
- IProject project = mWizard.getProject();
-
- String destination = ProjectHelper.loadStringProperty(project,
- ExportWizard.PROPERTY_DESTINATION);
- if (destination != null) {
- mDestination.setText(destination);
- }
- }
-
- // reset the wizard with no key/cert to make it not finishable, unless a valid
- // key/cert is found.
- mWizard.setSigningInfo(null, null);
-
- try {
- KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
- FileInputStream fis = new FileInputStream(mWizard.getKeystore());
- keyStore.load(fis, mWizard.getKeystorePassword());
- fis.close();
- PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(
- mWizard.getKeyAlias(),
- new KeyStore.PasswordProtection(mWizard.getKeyPassword()));
-
- if (entry != null) {
- mPrivateKey = entry.getPrivateKey();
- mCertificate = (X509Certificate)entry.getCertificate();
- } else {
- setErrorMessage("Unable to find key");
-
- setPageComplete(false);
- }
- } catch (FileNotFoundException e) {
- // this was checked at the first previous step and will not happen here, unless
- // the file was removed during the export wizard execution.
- onException(e);
- } catch (KeyStoreException e) {
- onException(e);
- } catch (NoSuchAlgorithmException e) {
- onException(e);
- } catch (UnrecoverableEntryException e) {
- onException(e);
- } catch (CertificateException e) {
- onException(e);
- } catch (IOException e) {
- onException(e);
- }
-
- if (mPrivateKey != null && mCertificate != null) {
- mFatalSigningError = false;
-
- Calendar expirationCalendar = Calendar.getInstance();
- expirationCalendar.setTime(mCertificate.getNotAfter());
- Calendar today = Calendar.getInstance();
-
- if (expirationCalendar.before(today)) {
- mDetailText.setText(String.format("<form><p>Certificate expired on %s</p></form>",
- mCertificate.getNotAfter().toString()),
- true /* parseTags */, true /* expandURLs */);
-
- // fatal error = nothing can make the page complete.
- mFatalSigningError = true;
-
- setErrorMessage("Certificate is expired!");
- setPageComplete(false);
- } else {
- // valid, key/cert: put it in the wizard so that it can be finished
- mWizard.setSigningInfo(mPrivateKey, mCertificate);
-
- StringBuilder sb = new StringBuilder(String.format("<form><p>Certificate expires on %s.</p>",
- mCertificate.getNotAfter().toString()));
-
- int expirationYear = expirationCalendar.get(Calendar.YEAR);
- int thisYear = today.get(Calendar.YEAR);
-
- if (thisYear + 25 < expirationYear) {
- // do nothing
- } else {
- if (expirationYear == thisYear) {
- sb.append("<p>The certificate expires this year!</p>");
- } else {
- int count = expirationYear-thisYear;
- sb.append(String.format("<p>The Certificate expires in %1$s %2$s!</p>",
- count, count == 1 ? "year" : "years"));
- }
-
- sb.append("<p>Make sure the certificate is valid for the planned lifetime of the product.</p>");
- sb.append("<p>If the certificate expires, you will be forced to sign your application with a different one.</p>");
- sb.append("<p>Applications cannot be upgraded if their certificate changes from one version to another, ");
- sb.append("forcing a full uninstall/install, which will make the user lose his/her data.</p>");
- sb.append("<p>Android Market currently requires certificates to be valid until 2033.</p>");
-
- sb.append("</form>");
- }
-
- mDetailText.setText(sb.toString(), true /* parseTags */, true /* expandURLs */);
- }
- mDetailText.getParent().layout();
- } else {
- // fatal error = nothing can make the page complete.
- mFatalSigningError = true;
- }
-
- onDestinationChange();
- }
-
- private void onDestinationChange() {
- if (mFatalSigningError == false) {
- String path = mDestination.getText().trim();
- if (path.length() == 0) {
- setErrorMessage("Enter destination for the APK file.");
- mWizard.setDestination(null); // this is to reset canFinish in the wizard
- setPageComplete(false);
- } else {
- File file = new File(path);
- if (file.isDirectory()) {
- setErrorMessage("Destination is a directory!");
- mWizard.setDestination(null); // this is to reset canFinish in the wizard
- setPageComplete(false);
- } else {
- File parentFile = file.getParentFile();
- if (parentFile == null || parentFile.isDirectory() == false) {
- setErrorMessage("Not a valid directory.");
- mWizard.setDestination(null); // this is to reset canFinish in the wizard
- setPageComplete(false);
- } else {
- mWizard.setDestination(path);
- setErrorMessage(null);
- setPageComplete(true);
- }
- }
- }
- }
- }
-
- /**
- * Calls {@link #setErrorMessage(String)} and {@link #setPageComplete(boolean)} based on a
- * {@link Throwable} object. If the {@link Throwable#getMessage()} returns <code>null</code>,
- * the method is called again on the cause of the Throwable.
- */
- private void onException(Throwable t) {
- String message = t.getMessage();
- if (message == null) {
- Throwable cause = t.getCause();
- if (cause != null) {
- onException(cause);
- } else {
- // no more cause and still no message. display the first exception.
- setErrorMessage(cause.getClass().getCanonicalName());
- setPageComplete(false);
- }
- return;
- }
-
- setErrorMessage(message);
- setPageComplete(false);
- }
-
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeyCheckPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeyCheckPage.java
new file mode 100644
index 0000000..c64bf10
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeyCheckPage.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.adt.project.export;
+
+import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.project.export.ExportWizard.ExportWizardPage;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.forms.widgets.FormText;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.UnrecoverableEntryException;
+import java.security.KeyStore.PrivateKeyEntry;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Calendar;
+
+/**
+ * Final page of the wizard that checks the key and ask for the ouput location.
+ */
+final class KeyCheckPage extends ExportWizardPage {
+
+ private final ExportWizard mWizard;
+ private PrivateKey mPrivateKey;
+ private X509Certificate mCertificate;
+ private Text mDestination;
+ private boolean mFatalSigningError;
+ private FormText mDetailText;
+
+ protected KeyCheckPage(ExportWizard wizard, String pageName) {
+ super(pageName);
+ mWizard = wizard;
+
+ setTitle("Destination and key/certificate checks");
+ setDescription(""); // TODO
+ }
+
+ public void createControl(Composite parent) {
+ setErrorMessage(null);
+ setMessage(null);
+
+ // build the ui.
+ Composite composite = new Composite(parent, SWT.NULL);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ GridLayout gl = new GridLayout(3, false);
+ gl.verticalSpacing *= 3;
+ composite.setLayout(gl);
+
+ GridData gd;
+
+ new Label(composite, SWT.NONE).setText("Destination APK file:");
+ mDestination = new Text(composite, SWT.BORDER);
+ mDestination.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ mDestination.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ onDestinationChange();
+ }
+ });
+ final Button browseButton = new Button(composite, SWT.PUSH);
+ browseButton.setText("Browse...");
+ browseButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ FileDialog fileDialog = new FileDialog(browseButton.getShell(), SWT.SAVE);
+
+ fileDialog.setText("Destination file name");
+ fileDialog.setFileName(mWizard.getApkFilename());
+
+ String saveLocation = fileDialog.open();
+ if (saveLocation != null) {
+ mDestination.setText(saveLocation);
+ }
+ }
+ });
+
+ mDetailText = new FormText(composite, SWT.NONE);
+ mDetailText.setLayoutData(gd = new GridData(GridData.FILL_BOTH));
+ gd.horizontalSpan = 3;
+
+ setControl(composite);
+ }
+
+ @Override
+ void onShow() {
+ // fill the texts with information loaded from the project.
+ if ((mProjectDataChanged & DATA_PROJECT) != 0) {
+ // reset the destination from the content of the project
+ IProject project = mWizard.getProject();
+
+ String destination = ProjectHelper.loadStringProperty(project,
+ ExportWizard.PROPERTY_DESTINATION);
+ if (destination != null) {
+ mDestination.setText(destination);
+ }
+ }
+
+ // if anything change we basically reload the data.
+ if (mProjectDataChanged != 0) {
+ mFatalSigningError = false;
+
+ // reset the wizard with no key/cert to make it not finishable, unless a valid
+ // key/cert is found.
+ mWizard.setSigningInfo(null, null);
+
+ if (mWizard.getKeystoreCreationMode() || mWizard.getKeyCreationMode()) {
+ int validity = mWizard.getValidity();
+ StringBuilder sb = new StringBuilder(
+ String.format("<form><p>Certificate expires in %d years.</p>",
+ validity));
+
+ if (validity < 25) {
+ sb.append("<p>Make sure the certificate is valid for the planned lifetime of the product.</p>");
+ sb.append("<p>If the certificate expires, you will be forced to sign your application with a different one.</p>");
+ sb.append("<p>Applications cannot be upgraded if their certificate changes from one version to another, ");
+ sb.append("forcing a full uninstall/install, which will make the user lose his/her data.</p>");
+ sb.append("<p>Android Market currently requires certificates to be valid until 2033.</p>");
+ }
+
+ sb.append("</form>");
+ mDetailText.setText(sb.toString(), true /* parseTags */, true /* expandURLs */);
+ } else {
+ try {
+ KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ FileInputStream fis = new FileInputStream(mWizard.getKeystore());
+ keyStore.load(fis, mWizard.getKeystorePassword().toCharArray());
+ fis.close();
+ PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(
+ mWizard.getKeyAlias(),
+ new KeyStore.PasswordProtection(
+ mWizard.getKeyPassword().toCharArray()));
+
+ if (entry != null) {
+ mPrivateKey = entry.getPrivateKey();
+ mCertificate = (X509Certificate)entry.getCertificate();
+ } else {
+ setErrorMessage("Unable to find key.");
+
+ setPageComplete(false);
+ }
+ } catch (FileNotFoundException e) {
+ // this was checked at the first previous step and will not happen here, unless
+ // the file was removed during the export wizard execution.
+ onException(e);
+ } catch (KeyStoreException e) {
+ onException(e);
+ } catch (NoSuchAlgorithmException e) {
+ onException(e);
+ } catch (UnrecoverableEntryException e) {
+ onException(e);
+ } catch (CertificateException e) {
+ onException(e);
+ } catch (IOException e) {
+ onException(e);
+ }
+
+ if (mPrivateKey != null && mCertificate != null) {
+ Calendar expirationCalendar = Calendar.getInstance();
+ expirationCalendar.setTime(mCertificate.getNotAfter());
+ Calendar today = Calendar.getInstance();
+
+ if (expirationCalendar.before(today)) {
+ mDetailText.setText(String.format(
+ "<form><p>Certificate expired on %s</p></form>",
+ mCertificate.getNotAfter().toString()),
+ true /* parseTags */, true /* expandURLs */);
+
+ // fatal error = nothing can make the page complete.
+ mFatalSigningError = true;
+
+ setErrorMessage("Certificate is expired.");
+ setPageComplete(false);
+ } else {
+ // valid, key/cert: put it in the wizard so that it can be finished
+ mWizard.setSigningInfo(mPrivateKey, mCertificate);
+
+ StringBuilder sb = new StringBuilder(String.format(
+ "<form><p>Certificate expires on %s.</p>",
+ mCertificate.getNotAfter().toString()));
+
+ int expirationYear = expirationCalendar.get(Calendar.YEAR);
+ int thisYear = today.get(Calendar.YEAR);
+
+ if (thisYear + 25 < expirationYear) {
+ // do nothing
+ } else {
+ if (expirationYear == thisYear) {
+ sb.append("<p>The certificate expires this year.</p>");
+ } else {
+ int count = expirationYear-thisYear;
+ sb.append(String.format(
+ "<p>The Certificate expires in %1$s %2$s.</p>",
+ count, count == 1 ? "year" : "years"));
+ }
+
+ sb.append("<p>Make sure the certificate is valid for the planned lifetime of the product.</p>");
+ sb.append("<p>If the certificate expires, you will be forced to sign your application with a different one.</p>");
+ sb.append("<p>Applications cannot be upgraded if their certificate changes from one version to another, ");
+ sb.append("forcing a full uninstall/install, which will make the user lose his/her data.</p>");
+ sb.append("<p>Android Market currently requires certificates to be valid until 2033.</p>");
+ }
+
+ sb.append("</form>");
+
+ mDetailText.setText(sb.toString(), true /* parseTags */, true /* expandURLs */);
+ }
+ mDetailText.getParent().layout();
+ } else {
+ // fatal error = nothing can make the page complete.
+ mFatalSigningError = true;
+ }
+ }
+ }
+
+ onDestinationChange();
+ }
+
+ private void onDestinationChange() {
+ if (mFatalSigningError == false) {
+ // reset messages for now.
+ setErrorMessage(null);
+ setMessage(null);
+
+ String path = mDestination.getText().trim();
+
+ if (path.length() == 0) {
+ setErrorMessage("Enter destination for the APK file.");
+ mWizard.setDestination(null); // this is to reset canFinish in the wizard
+ setPageComplete(false);
+ return;
+ }
+
+ File file = new File(path);
+ if (file.isDirectory()) {
+ setErrorMessage("Destination is a directory.");
+ mWizard.setDestination(null); // this is to reset canFinish in the wizard
+ setPageComplete(false);
+ return;
+ }
+
+ File parentFile = file.getParentFile();
+ if (parentFile == null || parentFile.isDirectory() == false) {
+ setErrorMessage("Not a valid directory.");
+ mWizard.setDestination(null); // this is to reset canFinish in the wizard
+ setPageComplete(false);
+ return;
+ }
+
+ // no error, set the destination in the wizard.
+ mWizard.setDestination(path);
+ setPageComplete(true);
+
+ // However, we should also test if the file already exists.
+ if (file.isFile()) {
+ setMessage("Destination file already exists.", WARNING);
+ }
+ }
+ }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeyCreationPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeyCreationPage.java
new file mode 100644
index 0000000..d7365f7
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeyCreationPage.java
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.adt.project.export;
+
+import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.project.export.ExportWizard.ExportWizardPage;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+import java.util.List;
+
+/**
+ * Key creation page.
+ */
+final class KeyCreationPage extends ExportWizardPage {
+
+ private final ExportWizard mWizard;
+ private Text mAlias;
+ private Text mKeyPassword;
+ private Text mKeyPassword2;
+ private Text mCnField;
+ private boolean mDisableOnChange = false;
+ private Text mOuField;
+ private Text mOField;
+ private Text mLField;
+ private Text mStField;
+ private Text mCField;
+ private String mDName;
+ private int mValidity = 0;
+ private List<String> mExistingAliases;
+
+
+ protected KeyCreationPage(ExportWizard wizard, String pageName) {
+ super(pageName);
+ mWizard = wizard;
+
+ setTitle("Key Creation");
+ setDescription(""); // TODO?
+ }
+
+ public void createControl(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NULL);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ GridLayout gl = new GridLayout(2, false);
+ composite.setLayout(gl);
+
+ GridData gd;
+
+ new Label(composite, SWT.NONE).setText("Alias:");
+ mAlias = new Text(composite, SWT.BORDER);
+ mAlias.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+
+ new Label(composite, SWT.NONE).setText("Password:");
+ mKeyPassword = new Text(composite, SWT.BORDER | SWT.PASSWORD);
+ mKeyPassword.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ mKeyPassword.addVerifyListener(sPasswordVerifier);
+
+ new Label(composite, SWT.NONE).setText("Confirm:");
+ mKeyPassword2 = new Text(composite, SWT.BORDER | SWT.PASSWORD);
+ mKeyPassword2.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ mKeyPassword2.addVerifyListener(sPasswordVerifier);
+
+ new Label(composite, SWT.NONE).setText("Validity (years):");
+ final Text validityText = new Text(composite, SWT.BORDER);
+ validityText.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ validityText.addVerifyListener(new VerifyListener() {
+ public void verifyText(VerifyEvent e) {
+ // check for digit only.
+ for (int i = 0 ; i < e.text.length(); i++) {
+ char letter = e.text.charAt(i);
+ if (letter < '0' || letter > '9') {
+ e.doit = false;
+ return;
+ }
+ }
+ }
+ });
+
+ new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL).setLayoutData(
+ gd = new GridData(GridData.FILL_HORIZONTAL));
+ gd.horizontalSpan = 2;
+
+ new Label(composite, SWT.NONE).setText("First and Last Name:");
+ mCnField = new Text(composite, SWT.BORDER);
+ mCnField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+
+ new Label(composite, SWT.NONE).setText("Organizational Unit:");
+ mOuField = new Text(composite, SWT.BORDER);
+ mOuField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+
+ new Label(composite, SWT.NONE).setText("Organization:");
+ mOField = new Text(composite, SWT.BORDER);
+ mOField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+
+ new Label(composite, SWT.NONE).setText("City or Locality:");
+ mLField = new Text(composite, SWT.BORDER);
+ mLField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+
+ new Label(composite, SWT.NONE).setText("State or Province:");
+ mStField = new Text(composite, SWT.BORDER);
+ mStField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+
+ new Label(composite, SWT.NONE).setText("Country Code (XX):");
+ mCField = new Text(composite, SWT.BORDER);
+ mCField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+
+ // Show description the first time
+ setErrorMessage(null);
+ setMessage(null);
+ setControl(composite);
+
+ mAlias.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ mWizard.setKeyAlias(mAlias.getText().trim());
+ onChange();
+ }
+ });
+ mKeyPassword.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ mWizard.setKeyPassword(mKeyPassword.getText());
+ onChange();
+ }
+ });
+ mKeyPassword2.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ onChange();
+ }
+ });
+
+ validityText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ try {
+ mValidity = Integer.parseInt(validityText.getText());
+ } catch (NumberFormatException e2) {
+ // this should only happen if the text field is empty due to the verifyListener.
+ mValidity = 0;
+ }
+ mWizard.setValidity(mValidity);
+ onChange();
+ }
+ });
+
+ ModifyListener dNameListener = new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ onDNameChange();
+ }
+ };
+
+ mCnField.addModifyListener(dNameListener);
+ mOuField.addModifyListener(dNameListener);
+ mOField.addModifyListener(dNameListener);
+ mLField.addModifyListener(dNameListener);
+ mStField.addModifyListener(dNameListener);
+ mCField.addModifyListener(dNameListener);
+ }
+
+ @Override
+ void onShow() {
+ // fill the texts with information loaded from the project.
+ if ((mProjectDataChanged & (DATA_PROJECT | DATA_KEYSTORE)) != 0) {
+ // reset the keystore/alias from the content of the project
+ IProject project = mWizard.getProject();
+
+ // disable onChange for now. we'll call it once at the end.
+ mDisableOnChange = true;
+
+ String alias = ProjectHelper.loadStringProperty(project, ExportWizard.PROPERTY_ALIAS);
+ if (alias != null) {
+ mAlias.setText(alias);
+ }
+
+ // get the existing list of keys if applicable
+ if (mWizard.getKeyCreationMode()) {
+ mExistingAliases = mWizard.getExistingAliases();
+ } else {
+ mExistingAliases = null;
+ }
+
+ // reset the passwords
+ mKeyPassword.setText(""); //$NON-NLS-1$
+ mKeyPassword2.setText(""); //$NON-NLS-1$
+
+ // enable onChange, and call it to display errors and enable/disable pageCompleted.
+ mDisableOnChange = false;
+ onChange();
+ }
+ }
+
+ @Override
+ public IWizardPage getPreviousPage() {
+ if (mWizard.getKeyCreationMode()) { // this means we create a key from an existing store
+ return mWizard.getKeySelectionPage();
+ }
+
+ return mWizard.getKeystoreSelectionPage();
+ }
+
+ @Override
+ public IWizardPage getNextPage() {
+ return mWizard.getKeyCheckPage();
+ }
+
+ /**
+ * Handles changes and update the error message and calls {@link #setPageComplete(boolean)}.
+ */
+ private void onChange() {
+ if (mDisableOnChange) {
+ return;
+ }
+
+ setErrorMessage(null);
+ setMessage(null);
+
+ if (mAlias.getText().trim().length() == 0) {
+ setErrorMessage("Enter key alias.");
+ setPageComplete(false);
+ return;
+ } else if (mExistingAliases != null) {
+ // we cannot use indexOf, because we need to do a case-insensitive check
+ String keyAlias = mAlias.getText().trim();
+ for (String alias : mExistingAliases) {
+ if (alias.equalsIgnoreCase(keyAlias)) {
+ setErrorMessage("Key alias already exists in keystore.");
+ setPageComplete(false);
+ return;
+ }
+ }
+ }
+
+ String value = mKeyPassword.getText();
+ if (value.length() == 0) {
+ setErrorMessage("Enter key password.");
+ setPageComplete(false);
+ return;
+ } else if (value.length() < 6) {
+ setErrorMessage("Key password is too short - must be at least 6 characters.");
+ setPageComplete(false);
+ return;
+ }
+
+ if (value.equals(mKeyPassword2.getText()) == false) {
+ setErrorMessage("Key passwords don't match.");
+ setPageComplete(false);
+ return;
+ }
+
+ if (mValidity == 0) {
+ setErrorMessage("Key certificate validity is required.");
+ setPageComplete(false);
+ return;
+ } else if (mValidity < 25) {
+ setMessage("A 25 year certificate validity is recommended.", WARNING);
+ } else if (mValidity > 1000) {
+ setErrorMessage("Key certificate validity must be between 1 and 1000 years.");
+ setPageComplete(false);
+ return;
+ }
+
+ if (mDName == null || mDName.length() == 0) {
+ setErrorMessage("At least one Certificate issuer field is required to be non-empty.");
+ setPageComplete(false);
+ return;
+ }
+
+ setPageComplete(true);
+ }
+
+ /**
+ * Handles changes in the DName fields.
+ */
+ private void onDNameChange() {
+ StringBuilder sb = new StringBuilder();
+
+ buildDName("CN", mCnField, sb);
+ buildDName("OU", mOuField, sb);
+ buildDName("O", mOField, sb);
+ buildDName("L", mLField, sb);
+ buildDName("ST", mStField, sb);
+ buildDName("C", mCField, sb);
+
+ mDName = sb.toString();
+ mWizard.setDName(mDName);
+
+ onChange();
+ }
+
+ /**
+ * Builds the distinguished name string with the provided {@link StringBuilder}.
+ * @param prefix the prefix of the entry.
+ * @param textField The {@link Text} field containing the entry value.
+ * @param sb the string builder containing the dname.
+ */
+ private void buildDName(String prefix, Text textField, StringBuilder sb) {
+ if (textField != null) {
+ String value = textField.getText().trim();
+ if (value.length() > 0) {
+ if (sb.length() > 0) {
+ sb.append(",");
+ }
+
+ sb.append(prefix);
+ sb.append('=');
+ sb.append(value);
+ }
+ }
+ }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeySelectionPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeySelectionPage.java
new file mode 100644
index 0000000..2fcd757
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeySelectionPage.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.adt.project.export;
+
+import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.project.export.ExportWizard.ExportWizardPage;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+/**
+ * Key Selection Page. This is used when an existing keystore is used.
+ */
+final class KeySelectionPage extends ExportWizardPage {
+
+ private final ExportWizard mWizard;
+ private Label mKeyAliasesLabel;
+ private Combo mKeyAliases;
+ private Label mKeyPasswordLabel;
+ private Text mKeyPassword;
+ private boolean mDisableOnChange = false;
+ private Button mUseExistingKey;
+ private Button mCreateKey;
+
+ protected KeySelectionPage(ExportWizard wizard, String pageName) {
+ super(pageName);
+ mWizard = wizard;
+
+ setTitle("Key alias selection");
+ setDescription(""); // TODO
+ }
+
+ public void createControl(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NULL);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ GridLayout gl = new GridLayout(3, false);
+ composite.setLayout(gl);
+
+ GridData gd;
+
+ mUseExistingKey = new Button(composite, SWT.RADIO);
+ mUseExistingKey.setText("Use existing key");
+ mUseExistingKey.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ gd.horizontalSpan = 3;
+ mUseExistingKey.setSelection(true);
+
+ new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData());
+ gd.heightHint = 0;
+ gd.widthHint = 50;
+ mKeyAliasesLabel = new Label(composite, SWT.NONE);
+ mKeyAliasesLabel.setText("Alias:");
+ mKeyAliases = new Combo(composite, SWT.READ_ONLY);
+ mKeyAliases.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData());
+ gd.heightHint = 0;
+ gd.widthHint = 50;
+ mKeyPasswordLabel = new Label(composite, SWT.NONE);
+ mKeyPasswordLabel.setText("Password:");
+ mKeyPassword = new Text(composite, SWT.BORDER | SWT.PASSWORD);
+ mKeyPassword.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ mCreateKey = new Button(composite, SWT.RADIO);
+ mCreateKey.setText("Create new key");
+ mCreateKey.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ gd.horizontalSpan = 3;
+
+ // Show description the first time
+ setErrorMessage(null);
+ setMessage(null);
+ setControl(composite);
+
+ mUseExistingKey.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ mWizard.setKeyCreationMode(!mUseExistingKey.getSelection());
+ enableWidgets();
+ onChange();
+ }
+ });
+
+ mKeyAliases.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ mWizard.setKeyAlias(mKeyAliases.getItem(mKeyAliases.getSelectionIndex()));
+ onChange();
+ }
+ });
+
+ mKeyPassword.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ mWizard.setKeyPassword(mKeyPassword.getText());
+ onChange();
+ }
+ });
+ }
+
+ @Override
+ void onShow() {
+ // fill the texts with information loaded from the project.
+ if ((mProjectDataChanged & (DATA_PROJECT | DATA_KEYSTORE)) != 0) {
+ // disable onChange for now. we'll call it once at the end.
+ mDisableOnChange = true;
+
+ // reset the alias from the content of the project
+ try {
+ // reset to using a key
+ mWizard.setKeyCreationMode(false);
+ mUseExistingKey.setSelection(true);
+ mCreateKey.setSelection(false);
+ enableWidgets();
+
+ // remove the content of the alias combo always and first, in case the
+ // keystore password is wrong
+ mKeyAliases.removeAll();
+
+ // get the alias list (also used as a keystore password test)
+ KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ FileInputStream fis = new FileInputStream(mWizard.getKeystore());
+ keyStore.load(fis, mWizard.getKeystorePassword().toCharArray());
+ fis.close();
+
+ Enumeration<String> aliases = keyStore.aliases();
+
+ // get the alias from the project previous export, and look for a match as
+ // we add the aliases to the combo.
+ IProject project = mWizard.getProject();
+
+ String keyAlias = ProjectHelper.loadStringProperty(project,
+ ExportWizard.PROPERTY_ALIAS);
+
+ ArrayList<String> aliasList = new ArrayList<String>();
+
+ int selection = -1;
+ int count = 0;
+ while (aliases.hasMoreElements()) {
+ String alias = aliases.nextElement();
+ mKeyAliases.add(alias);
+ aliasList.add(alias);
+ if (selection == -1 && alias.equalsIgnoreCase(keyAlias)) {
+ selection = count;
+ }
+ count++;
+ }
+
+ mWizard.setExistingAliases(aliasList);
+
+ if (selection != -1) {
+ mKeyAliases.select(selection);
+
+ // since a match was found and is selected, we need to give it to
+ // the wizard as well
+ mWizard.setKeyAlias(keyAlias);
+ } else {
+ mKeyAliases.clearSelection();
+ }
+
+ // reset the password
+ mKeyPassword.setText(""); //$NON-NLS-1$
+
+ // enable onChange, and call it to display errors and enable/disable pageCompleted.
+ mDisableOnChange = false;
+ onChange();
+ } catch (KeyStoreException e) {
+ onException(e);
+ } catch (FileNotFoundException e) {
+ onException(e);
+ } catch (NoSuchAlgorithmException e) {
+ onException(e);
+ } catch (CertificateException e) {
+ onException(e);
+ } catch (IOException e) {
+ onException(e);
+ } finally {
+ // in case we exit with an exception, we need to reset this
+ mDisableOnChange = false;
+ }
+ }
+ }
+
+ @Override
+ public IWizardPage getPreviousPage() {
+ return mWizard.getKeystoreSelectionPage();
+ }
+
+ @Override
+ public IWizardPage getNextPage() {
+ if (mWizard.getKeyCreationMode()) {
+ return mWizard.getKeyCreationPage();
+ }
+
+ return mWizard.getKeyCheckPage();
+ }
+
+ /**
+ * Handles changes and update the error message and calls {@link #setPageComplete(boolean)}.
+ */
+ private void onChange() {
+ if (mDisableOnChange) {
+ return;
+ }
+
+ setErrorMessage(null);
+ setMessage(null);
+
+ if (mWizard.getKeyCreationMode() == false) {
+ if (mKeyAliases.getSelectionIndex() == -1) {
+ setErrorMessage("Select a key alias.");
+ setPageComplete(false);
+ return;
+ }
+
+ if (mKeyPassword.getText().trim().length() == 0) {
+ setErrorMessage("Enter key password.");
+ setPageComplete(false);
+ return;
+ }
+ }
+
+ setPageComplete(true);
+ }
+
+ private void enableWidgets() {
+ boolean useKey = !mWizard.getKeyCreationMode();
+ mKeyAliasesLabel.setEnabled(useKey);
+ mKeyAliases.setEnabled(useKey);
+ mKeyPassword.setEnabled(useKey);
+ mKeyPasswordLabel.setEnabled(useKey);
+ }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeystoreSelectionPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeystoreSelectionPage.java
new file mode 100644
index 0000000..c5a4d47
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeystoreSelectionPage.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.adt.project.export;
+
+import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.project.export.ExportWizard.ExportWizardPage;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+import java.io.File;
+
+/**
+ * Keystore selection page. This page allows to choose to create a new keystore or use an
+ * existing one.
+ */
+final class KeystoreSelectionPage extends ExportWizardPage {
+
+ private final ExportWizard mWizard;
+ private Button mUseExistingKeystore;
+ private Button mCreateKeystore;
+ private Text mKeystore;
+ private Text mKeystorePassword;
+ private Label mConfirmLabel;
+ private Text mKeystorePassword2;
+ private boolean mDisableOnChange = false;
+
+ protected KeystoreSelectionPage(ExportWizard wizard, String pageName) {
+ super(pageName);
+ mWizard = wizard;
+
+ setTitle("Keystore selection");
+ setDescription(""); //TODO
+ }
+
+ public void createControl(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NULL);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ GridLayout gl = new GridLayout(3, false);
+ composite.setLayout(gl);
+
+ GridData gd;
+
+ mUseExistingKeystore = new Button(composite, SWT.RADIO);
+ mUseExistingKeystore.setText("Use existing keystore");
+ mUseExistingKeystore.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ gd.horizontalSpan = 3;
+ mUseExistingKeystore.setSelection(true);
+
+ mCreateKeystore = new Button(composite, SWT.RADIO);
+ mCreateKeystore.setText("Create new keystore");
+ mCreateKeystore.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ gd.horizontalSpan = 3;
+
+ new Label(composite, SWT.NONE).setText("Location:");
+ mKeystore = new Text(composite, SWT.BORDER);
+ mKeystore.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ final Button browseButton = new Button(composite, SWT.PUSH);
+ browseButton.setText("Browse...");
+ browseButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ FileDialog fileDialog;
+ if (mUseExistingKeystore.getSelection()) {
+ fileDialog = new FileDialog(browseButton.getShell(),SWT.OPEN);
+ fileDialog.setText("Load Keystore");
+ } else {
+ fileDialog = new FileDialog(browseButton.getShell(),SWT.SAVE);
+ fileDialog.setText("Select Keystore Name");
+ }
+
+ String fileName = fileDialog.open();
+ if (fileName != null) {
+ mKeystore.setText(fileName);
+ }
+ }
+ });
+
+ new Label(composite, SWT.NONE).setText("Password:");
+ mKeystorePassword = new Text(composite, SWT.BORDER | SWT.PASSWORD);
+ mKeystorePassword.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ mKeystorePassword.addVerifyListener(sPasswordVerifier);
+ new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData());
+ gd.heightHint = gd.widthHint = 0;
+
+ mConfirmLabel = new Label(composite, SWT.NONE);
+ mConfirmLabel.setText("Confirm:");
+ mKeystorePassword2 = new Text(composite, SWT.BORDER | SWT.PASSWORD);
+ mKeystorePassword2.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ mKeystorePassword2.addVerifyListener(sPasswordVerifier);
+ new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData());
+ gd.heightHint = gd.widthHint = 0;
+ mKeystorePassword2.setEnabled(false);
+
+ // Show description the first time
+ setErrorMessage(null);
+ setMessage(null);
+ setControl(composite);
+
+ mUseExistingKeystore.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ boolean createStore = !mUseExistingKeystore.getSelection();
+ mKeystorePassword2.setEnabled(createStore);
+ mConfirmLabel.setEnabled(createStore);
+ mWizard.setKeystoreCreationMode(createStore);
+ onChange();
+ }
+ });
+
+ mKeystore.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ mWizard.setKeystore(mKeystore.getText().trim());
+ onChange();
+ }
+ });
+
+ mKeystorePassword.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ mWizard.setKeystorePassword(mKeystorePassword.getText());
+ onChange();
+ }
+ });
+
+ mKeystorePassword2.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ onChange();
+ }
+ });
+ }
+
+ @Override
+ public IWizardPage getNextPage() {
+ if (mUseExistingKeystore.getSelection()) {
+ return mWizard.getKeySelectionPage();
+ }
+
+ return mWizard.getKeyCreationPage();
+ }
+
+ @Override
+ void onShow() {
+ // fill the texts with information loaded from the project.
+ if ((mProjectDataChanged & DATA_PROJECT) != 0) {
+ // reset the keystore/alias from the content of the project
+ IProject project = mWizard.getProject();
+
+ // disable onChange for now. we'll call it once at the end.
+ mDisableOnChange = true;
+
+ String keystore = ProjectHelper.loadStringProperty(project,
+ ExportWizard.PROPERTY_KEYSTORE);
+ if (keystore != null) {
+ mKeystore.setText(keystore);
+ }
+
+ // reset the passwords
+ mKeystorePassword.setText(""); //$NON-NLS-1$
+ mKeystorePassword2.setText(""); //$NON-NLS-1$
+
+ // enable onChange, and call it to display errors and enable/disable pageCompleted.
+ mDisableOnChange = false;
+ onChange();
+ }
+ }
+
+ /**
+ * Handles changes and update the error message and calls {@link #setPageComplete(boolean)}.
+ */
+ private void onChange() {
+ if (mDisableOnChange) {
+ return;
+ }
+
+ setErrorMessage(null);
+ setMessage(null);
+
+ boolean createStore = !mUseExistingKeystore.getSelection();
+
+ // checks the keystore path is non null.
+ String keystore = mKeystore.getText().trim();
+ if (keystore.length() == 0) {
+ setErrorMessage("Enter path to keystore.");
+ setPageComplete(false);
+ return;
+ } else {
+ File f = new File(keystore);
+ if (f.exists() == false) {
+ if (createStore == false) {
+ setErrorMessage("Keystore does not exist.");
+ setPageComplete(false);
+ return;
+ }
+ } else if (f.isDirectory()) {
+ setErrorMessage("Keystore path is a directory.");
+ setPageComplete(false);
+ return;
+ } else if (f.isFile()) {
+ if (createStore) {
+ setErrorMessage("File already exists.");
+ setPageComplete(false);
+ return;
+ }
+ }
+ }
+
+ String value = mKeystorePassword.getText();
+ if (value.length() == 0) {
+ setErrorMessage("Enter keystore password.");
+ setPageComplete(false);
+ return;
+ } else if (createStore && value.length() < 6) {
+ setErrorMessage("Keystore password is too short - must be at least 6 characters.");
+ setPageComplete(false);
+ return;
+ }
+
+ if (createStore) {
+ if (mKeystorePassword2.getText().length() == 0) {
+ setErrorMessage("Confirm keystore password.");
+ setPageComplete(false);
+ return;
+ }
+
+ if (mKeystorePassword.getText().equals(mKeystorePassword2.getText()) == false) {
+ setErrorMessage("Keystore passwords do not match.");
+ setPageComplete(false);
+ return;
+ }
+ }
+
+ setPageComplete(true);
+ }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/PreExportPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ProjectCheckPage.java
similarity index 95%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/PreExportPage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ProjectCheckPage.java
index 5fc204d..3614be3 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/PreExportPage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ProjectCheckPage.java
@@ -47,7 +47,7 @@
/**
* First Export Wizard Page. Display warning/errors.
*/
-public class PreExportPage extends ExportWizardPage {
+final class ProjectCheckPage extends ExportWizardPage {
private final static String IMG_ERROR = "error.png"; //$NON-NLS-1$
private final static String IMG_WARNING = "warning.png"; //$NON-NLS-1$
@@ -60,12 +60,13 @@
private Composite mErrorComposite;
private Text mProjectText;
private ProjectChooserHelper mProjectChooserHelper;
+ private boolean mFirstOnShow = true;
- protected PreExportPage(ExportWizard wizard, String pageName) {
+ protected ProjectCheckPage(ExportWizard wizard, String pageName) {
super(pageName);
mWizard = wizard;
- setTitle("Pre Export Checks");
+ setTitle("Project Checks");
setDescription("Performs a set of checks to make sure the application can be exported.");
}
@@ -123,10 +124,14 @@
@Override
void onShow() {
- // get the project and init the ui
- IProject project = mWizard.getProject();
- if (project != null) {
- mProjectText.setText(project.getName());
+ if (mFirstOnShow) {
+ // get the project and init the ui
+ IProject project = mWizard.getProject();
+ if (project != null) {
+ mProjectText.setText(project.getName());
+ }
+
+ mFirstOnShow = false;
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/SigningExportPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/SigningExportPage.java
deleted file mode 100644
index 5e7ed0f..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/SigningExportPage.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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.ide.eclipse.adt.project.export;
-
-import com.android.ide.eclipse.adt.project.ProjectHelper;
-import com.android.ide.eclipse.adt.project.export.ExportWizard.ExportWizardPage;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.FileDialog;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Text;
-
-import java.io.File;
-
-/**
- * Second export wizard page.
- */
-public class SigningExportPage extends ExportWizardPage {
-
- private final ExportWizard mWizard;
- private Text mKeystore;
- private Text mAlias;
- private Text mKeystorePassword;
- private Text mKeyPassword;
- private boolean mDisableOnChange = false;
-
- protected SigningExportPage(ExportWizard wizard, String pageName) {
- super(pageName);
- mWizard = wizard;
-
- setTitle("Application Signing");
- setDescription("Defines which store, key and certificate to use to sign the Android Application.");
- }
-
- public void createControl(Composite parent) {
- Composite composite = new Composite(parent, SWT.NULL);
- composite.setLayoutData(new GridData(GridData.FILL_BOTH));
- GridLayout gl = new GridLayout(3, false);
- composite.setLayout(gl);
-
- GridData gd;
-
- new Label(composite, SWT.NONE).setText("Keystore:");
- mKeystore = new Text(composite, SWT.BORDER);
- mKeystore.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
- final Button browseButton = new Button(composite, SWT.PUSH);
- browseButton.setText("Browse...");
- browseButton.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- FileDialog fileDialog = new FileDialog(browseButton.getShell(), SWT.OPEN);
- fileDialog.setText("Load Keystore");
-
- String fileName = fileDialog.open();
- if (fileName != null) {
- mKeystore.setText(fileName);
- }
- }
- });
-
- new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData());
- gd.horizontalSpan = 2;
- gd.heightHint = 0;
- new Button(composite, SWT.PUSH).setText("New...");
-
- new Label(composite, SWT.NONE).setText("Key Alias:");
- mAlias = new Text(composite, SWT.BORDER);
- mAlias.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
-
- new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL).setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
- gd.horizontalSpan = 3;
-
- new Label(composite, SWT.NONE).setText("Store password:");
- mKeystorePassword = new Text(composite, SWT.BORDER | SWT.PASSWORD);
- mKeystorePassword.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
- new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData());
- gd.heightHint = gd.widthHint = 0;
-
- new Label(composite, SWT.NONE).setText("Key password:");
- mKeyPassword = new Text(composite, SWT.BORDER | SWT.PASSWORD);
- mKeyPassword.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
-
- // Show description the first time
- setErrorMessage(null);
- setMessage(null);
- setControl(composite);
-
- mKeystore.addModifyListener(new ModifyListener() {
- public void modifyText(ModifyEvent e) {
- mWizard.setKeystore(mKeystore.getText().trim());
- onChange();
- }
- });
- mAlias.addModifyListener(new ModifyListener() {
- public void modifyText(ModifyEvent e) {
- mWizard.setKeyAlias(mAlias.getText().trim());
- onChange();
- }
- });
- mKeystorePassword.addModifyListener(new ModifyListener() {
- public void modifyText(ModifyEvent e) {
- mWizard.setKeystorePassword(mKeystorePassword.getText().trim().toCharArray());
- onChange();
- }
- });
- mKeyPassword.addModifyListener(new ModifyListener() {
- public void modifyText(ModifyEvent e) {
- mWizard.setKeyPassword(mKeyPassword.getText().trim().toCharArray());
- onChange();
- }
- });
- }
-
- @Override
- void onShow() {
- // fill the texts with information loaded from the project.
- if (mNewProjectReference) {
- // reset the keystore/alias from the content of the project
- IProject project = mWizard.getProject();
-
- // disable onChange for now. we'll call it once at the end.
- mDisableOnChange = true;
-
- String keystore = ProjectHelper.loadStringProperty(project,
- ExportWizard.PROPERTY_KEYSTORE);
- if (keystore != null) {
- mKeystore.setText(keystore);
- }
-
- String alias = ProjectHelper.loadStringProperty(project, ExportWizard.PROPERTY_ALIAS);
- if (alias != null) {
- mAlias.setText(alias);
- }
-
- // reset the passwords
- mKeystorePassword.setText(""); //$NON-NLS-1$
- mKeyPassword.setText(""); //$NON-NLS-1$
-
- // enable onChange, and call it to display errors and enable/disable pageCompleted.
- mDisableOnChange = false;
- onChange();
- }
- }
-
- /**
- * Handles changes and update the error message and calls {@link #setPageComplete(boolean)}.
- */
- private void onChange() {
- if (mDisableOnChange) {
- return;
- }
-
- setErrorMessage(null);
- setMessage(null);
-
- // checks the keystore path is non null.
- String keystore = mKeystore.getText().trim();
- if (keystore.length() == 0) {
- setErrorMessage("Enter path to keystore.");
- setPageComplete(false);
- return;
- } else {
- File f = new File(keystore);
- if (f.exists() == false) {
- setErrorMessage("Keystore does not exists!");
- setPageComplete(false);
- return;
- } else if (f.isDirectory()) {
- setErrorMessage("Keystore is a directory!");
- setPageComplete(false);
- return;
- }
- }
-
- if (mAlias.getText().trim().length() == 0) {
- setErrorMessage("Enter key alias.");
- setPageComplete(false);
- return;
- }
-
- if (mKeystorePassword.getText().trim().length() == 0) {
- setErrorMessage("Enter keystore password.");
- setPageComplete(false);
- return;
- }
-
- if (mKeyPassword.getText().trim().length() == 0) {
- setErrorMessage("Enter key password.");
- setPageComplete(false);
- return;
- }
-
- setPageComplete(true);
- }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainer.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainer.java
index d7b290b..945fe52 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainer.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainer.java
@@ -27,16 +27,19 @@
private IClasspathEntry[] mClasspathEntry;
private IPath mContainerPath;
+ private String mName;
/**
* Constructs the container with the {@link IClasspathEntry} representing the android
* framework jar file and the container id
* @param entry the entry representing the android framework.
* @param path the path containing the classpath container id.
+ * @param name the name of the container to display.
*/
- AndroidClasspathContainer(IClasspathEntry entry, IPath path) {
+ AndroidClasspathContainer(IClasspathEntry entry, IPath path, String name) {
mClasspathEntry = new IClasspathEntry[] { entry };
mContainerPath = path;
+ mName = name;
}
public IClasspathEntry[] getClasspathEntries() {
@@ -44,7 +47,7 @@
}
public String getDescription() {
- return "Android Library";
+ return mName;
}
public int getKind() {
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainerInitializer.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainerInitializer.java
index 5dca350..2cafa01 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainerInitializer.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainerInitializer.java
@@ -16,10 +16,16 @@
package com.android.ide.eclipse.adt.project.internal;
+import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.sdk.LoadStatus;
+import com.android.ide.eclipse.adt.sdk.Sdk;
+import com.android.ide.eclipse.common.project.BaseProjectHelper;
+import com.android.sdklib.IAndroidTarget;
+import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
@@ -38,10 +44,6 @@
* {@link IProject}s. This removes the hard-coded path to the android.jar.
*/
public class AndroidClasspathContainerInitializer extends ClasspathContainerInitializer {
- /** The old container id */
- private final static String OLD_CONTAINER_ID =
- "com.android.ide.eclipse.adt.project.AndroidClasspathContainerInitializer"; //$NON-NLS-1$
-
/** The container id for the android framework jar file */
private final static String CONTAINER_ID =
"com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"; //$NON-NLS-1$
@@ -58,17 +60,10 @@
*/
@Override
public void initialize(IPath containerPath, IJavaProject project) throws CoreException {
- String id = null;
- if (OLD_CONTAINER_ID.equals(containerPath.toString())) {
- id = OLD_CONTAINER_ID;
- } else if (CONTAINER_ID.equals(containerPath.toString())) {
- id = CONTAINER_ID;
- }
-
- if (id != null) {
- JavaCore.setClasspathContainer(new Path(id),
+ if (CONTAINER_ID.equals(containerPath.toString())) {
+ JavaCore.setClasspathContainer(new Path(CONTAINER_ID),
new IJavaProject[] { project },
- new IClasspathContainer[] { allocateAndroidContainer(id) },
+ new IClasspathContainer[] { allocateAndroidContainer(CONTAINER_ID, project) },
new NullProgressMonitor());
}
}
@@ -82,15 +77,6 @@
}
/**
- * Checks the {@link IPath} objects against the old android framework container id and
- * returns <code>true</code> if they are identical.
- * @param path the <code>IPath</code> to check.
- */
- public static boolean checkOldPath(IPath path) {
- return OLD_CONTAINER_ID.equals(path.toString());
- }
-
- /**
* Checks the {@link IPath} objects against the android framework container id and
* returns <code>true</code> if they are identical.
* @param path the <code>IPath</code> to check.
@@ -106,41 +92,18 @@
* @return <code>true</code> if success, <code>false</code> otherwise.
*/
public static boolean updateProjects(IJavaProject[] androidProjects) {
-
try {
- // because those projects could have the old id, we are going to fix
- // them dynamically here.
- for (IJavaProject javaProject: androidProjects) {
- IClasspathEntry[] entries = javaProject.getRawClasspath();
-
- int containerIndex = ProjectHelper.findClasspathEntryByPath(entries,
- OLD_CONTAINER_ID,
- IClasspathEntry.CPE_CONTAINER);
- if (containerIndex != -1) {
- // the project has the old container, we remove it
- entries = ProjectHelper.removeEntryFromClasspath(entries, containerIndex);
-
- // we add the new one instead
- entries = ProjectHelper.addEntryToClasspath(entries, getContainerEntry());
-
- // and give the new entries to the project
- javaProject.setRawClasspath(entries, new NullProgressMonitor());
- }
- }
-
// Allocate a new AndroidClasspathContainer, and associate it to the android framework
// container id for each projects.
// By providing a new association between a container id and a IClasspathContainer,
// this forces the JDT to query the IClasspathContainer for new IClasspathEntry (with
// IClasspathContainer#getClasspathEntries()), and therefore force recompilation of
// the projects.
- // TODO: We could only do that for the projects haven't fixed above
- // (this isn't something that will happen a lot though)
int projectCount = androidProjects.length;
IClasspathContainer[] containers = new IClasspathContainer[projectCount];
for (int i = 0 ; i < projectCount; i++) {
- containers[i] = allocateAndroidContainer(CONTAINER_ID);
+ containers[i] = allocateAndroidContainer(CONTAINER_ID, androidProjects[i]);
}
// give each project their new container in one call.
@@ -158,23 +121,123 @@
* Allocates and returns an {@link AndroidClasspathContainer} object with the proper
* path to the framework jar file.
* @param containerId the container id to be used.
+ * @param javaProject The java project that will receive the container.
*/
- private static IClasspathContainer allocateAndroidContainer(String containerId) {
- return new AndroidClasspathContainer(createFrameworkClasspath(), new Path(containerId));
+ private static IClasspathContainer allocateAndroidContainer(String containerId,
+ IJavaProject javaProject) {
+ IProject iProject = javaProject.getProject();
+
+ // remove potential MARKER_TARGETs.
+ try {
+ if (iProject.exists()) {
+ iProject.deleteMarkers(AdtConstants.MARKER_TARGET, true,
+ IResource.DEPTH_INFINITE);
+ }
+ } catch (CoreException ce) {
+ // just log the error
+ AdtPlugin.log(ce, "Error removing target marker.");
+ }
+
+
+ // first we check if the SDK has been loaded
+ boolean sdkIsLoaded = AdtPlugin.getDefault().getSdkLoadStatus(javaProject) ==
+ LoadStatus.LOADED;
+
+ // then we check if the project has a valid target.
+ IAndroidTarget target = null;
+ if (sdkIsLoaded) {
+ target = Sdk.getCurrent().getTarget(iProject);
+ }
+
+ // if we are loaded and the target is non null, we create a valid ClassPathContainer
+ if (sdkIsLoaded && target != null) {
+ String targetName = null;
+ if (target.isPlatform()) {
+ targetName = target.getName();
+ } else {
+ targetName = String.format("%1$s (%2$s)", target.getName(),
+ target.getApiVersionName());
+ }
+
+ return new AndroidClasspathContainer(createFrameworkClasspath(target),
+ new Path(containerId), targetName);
+ }
+
+ // else we put a marker on the project, and return a dummy container (to replace the
+ // previous one if there was one.)
+
+ // Get the project's target's hash string (if it exists)
+ String hashString = Sdk.getProjectTargetHashString(iProject);
+
+ String message = null;
+ boolean outputToConsole = true;
+ if (hashString == null || hashString.length() == 0) {
+ message = String.format(
+ "Project has no target set. Edit the project properties to set one.");
+ } else if (sdkIsLoaded) {
+ message = String.format(
+ "Unable to resolve target '%s'", hashString);
+ } else {
+ // this is the case where there is a hashString but the SDK is not yet
+ // loaded and therefore we can't get the target yet.
+ message = String.format(
+ "Unable to resolve target '%s' until the SDK is loaded.", hashString);
+
+ // let's not log this one to the console as it will happen at every boot,
+ // and it's expected. (we do keep the error marker though).
+ outputToConsole = false;
+ }
+
+ // log the error and put the marker on the project
+ if (outputToConsole) {
+ AdtPlugin.printBuildToConsole(AdtConstants.BUILD_ALWAYS, iProject, message);
+ }
+ IMarker marker = BaseProjectHelper.addMarker(iProject, AdtConstants.MARKER_TARGET, message,
+ IMarker.SEVERITY_ERROR);
+
+ // add a marker priority as this is an more important error than the error that will
+ // spring from the lack of library
+ try {
+ marker.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH);
+ } catch (CoreException e) {
+ // just log the error
+ AdtPlugin.log(e, "Error changing target marker priority.");
+ }
+
+ // return a dummy container to replace the one we may have had before.
+ return new IClasspathContainer() {
+ public IClasspathEntry[] getClasspathEntries() {
+ return new IClasspathEntry[0];
+ }
+
+ public String getDescription() {
+ return "Unable to get system library for the project";
+ }
+
+ public int getKind() {
+ return IClasspathContainer.K_DEFAULT_SYSTEM;
+ }
+
+ public IPath getPath() {
+ return null;
+ }
+ };
}
/**
- * Creates and returns a new {@link IClasspathEntry} object for the android framework.
- * <p/>This references the OS path to the android.jar and the java doc directory. This is
- * dynamically created when a project is opened, and never saved in the project itself, so
- * there's no risk of storing an obsolete path.
+ * Creates and returns a new {@link IClasspathEntry} object for the android
+ * framework. <p/>This references the OS path to the android.jar and the
+ * java doc directory. This is dynamically created when a project is opened,
+ * and never saved in the project itself, so there's no risk of storing an
+ * obsolete path.
+ *
+ * @param target The target that contains the libraries.
*/
- private static IClasspathEntry createFrameworkClasspath() {
+ private static IClasspathEntry createFrameworkClasspath(IAndroidTarget target) {
// now add the android framework to the class path.
// create the path object.
- IPath android_lib = new Path(AdtPlugin.getOsAbsoluteFramework());
-
- IPath android_src = new Path(AdtPlugin.getOsAbsoluteAndroidSources());
+ IPath android_lib = new Path(target.getPath(IAndroidTarget.ANDROID_JAR));
+ IPath android_src = new Path(target.getPath(IAndroidTarget.SOURCES));
// create the java doc link.
IClasspathAttribute cpAttribute = JavaCore.newClasspathAttribute(
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/properties/AndroidPropertyPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/properties/AndroidPropertyPage.java
new file mode 100644
index 0000000..584dd0d
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/properties/AndroidPropertyPage.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.adt.project.properties;
+
+import com.android.ide.eclipse.adt.sdk.Sdk;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdkuilib.SdkTargetSelector;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.IWorkbenchPropertyPage;
+import org.eclipse.ui.dialogs.PropertyPage;
+
+/**
+ * Property page for "Android" project.
+ * This is accessible from the Package Explorer when right clicking a project and choosing
+ * "Properties".
+ *
+ */
+public class AndroidPropertyPage extends PropertyPage implements IWorkbenchPropertyPage {
+
+ private IProject mProject;
+ private SdkTargetSelector mSelector;
+
+ public AndroidPropertyPage() {
+ // pass
+ }
+
+ @Override
+ protected Control createContents(Composite parent) {
+ // get the element (this is not yet valid in the constructor).
+ mProject = (IProject)getElement();
+
+ Composite top = new Composite(parent, SWT.NONE);
+ top.setLayoutData(new GridData(GridData.FILL_BOTH));
+ top.setLayout(new GridLayout(1, false));
+
+ Label l = new Label(top, SWT.NONE);
+ l.setText("Project Target");
+
+ // get the targets from the sdk
+ IAndroidTarget[] targets = null;
+ if (Sdk.getCurrent() != null) {
+ targets = Sdk.getCurrent().getTargets();
+ }
+
+ // build the UI.
+ mSelector = new SdkTargetSelector(top, targets, false /*allowMultipleSelection*/);
+
+ if (Sdk.getCurrent() != null) {
+ IAndroidTarget target = Sdk.getCurrent().getTarget(mProject);
+ if (target != null) {
+ mSelector.setSelection(target);
+ }
+ }
+
+ mSelector.setSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ // look for the selection and validate the page if there is a selection
+ IAndroidTarget target = mSelector.getFirstSelected();
+ setValid(target != null);
+ }
+ });
+
+ return top;
+ }
+
+ @Override
+ public boolean performOk() {
+ if (Sdk.getCurrent() != null) {
+ Sdk.getCurrent().setProject(mProject, mSelector.getFirstSelected());
+ }
+
+ return true;
+ }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/AndroidJarLoader.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidJarLoader.java
similarity index 92%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/AndroidJarLoader.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidJarLoader.java
index 8c37f05..fad4f19 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/AndroidJarLoader.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidJarLoader.java
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.resources;
+package com.android.ide.eclipse.adt.sdk;
-import com.android.ide.eclipse.adt.resources.LayoutParamsParser.IClass;
import com.android.ide.eclipse.common.AndroidConstants;
import org.eclipse.core.runtime.IProgressMonitor;
@@ -35,9 +34,12 @@
/**
* Custom class loader able to load a class from the SDK jar file.
*/
-public class AndroidJarLoader extends ClassLoader implements IAndroidLoader {
+public class AndroidJarLoader extends ClassLoader implements IAndroidClassLoader {
- public final static class ClassWrapper implements IClass {
+ /**
+ * Wrapper around a {@link Class} to provide the methods of {@link IClassDescriptor}.
+ */
+ public final static class ClassWrapper implements IClassDescriptor {
private Class<?> mClass;
public ClassWrapper(Class<?> clazz) {
@@ -48,9 +50,9 @@
return mClass.getCanonicalName();
}
- public IClass[] getDeclaredClasses() {
+ public IClassDescriptor[] getDeclaredClasses() {
Class<?>[] classes = mClass.getDeclaredClasses();
- IClass[] iclasses = new IClass[classes.length];
+ IClassDescriptor[] iclasses = new IClassDescriptor[classes.length];
for (int i = 0 ; i < classes.length ; i++) {
iclasses[i] = new ClassWrapper(classes[i]);
}
@@ -58,7 +60,7 @@
return iclasses;
}
- public IClass getEnclosingClass() {
+ public IClassDescriptor getEnclosingClass() {
return new ClassWrapper(mClass.getEnclosingClass());
}
@@ -66,7 +68,7 @@
return mClass.getSimpleName();
}
- public IClass getSuperclass() {
+ public IClassDescriptor getSuperclass() {
return new ClassWrapper(mClass.getSuperclass());
}
@@ -131,17 +133,18 @@
* @param packageFilter The package that contains all the class data to preload, using a fully
* qualified binary name (.e.g "com.my.package."). The matching algorithm
* is simple "startsWith". Use an empty string to include everything.
+ * @param taskLabel An optional task name for the sub monitor. Can be null.
* @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
* @throws IOException
* @throws InvalidAttributeValueException
* @throws ClassFormatError
*/
- public void preLoadClasses(String packageFilter, IProgressMonitor monitor)
+ public void preLoadClasses(String packageFilter, String taskLabel, IProgressMonitor monitor)
throws IOException, InvalidAttributeValueException, ClassFormatError {
// Transform the package name into a zip entry path
String pathFilter = packageFilter.replaceAll("\\.", "/"); //$NON-NLS-1$ //$NON-NLS-2$
- SubMonitor progress = SubMonitor.convert(monitor, 100);
+ SubMonitor progress = SubMonitor.convert(monitor, taskLabel == null ? "" : taskLabel, 100);
// create streams to read the intermediary archive
FileInputStream fis = new FileInputStream(mOsFrameworkLocation);
@@ -174,6 +177,7 @@
// advance 5% of whatever is allocated on the progress bar
progress.setWorkRemaining(100);
progress.worked(5);
+ progress.subTask(String.format("Preload %1$s", className));
}
}
@@ -193,17 +197,18 @@
* @throws InvalidAttributeValueException
* @throws ClassFormatError
*/
- public HashMap<String, ArrayList<IClass>> findClassesDerivingFrom(
+ public HashMap<String, ArrayList<IClassDescriptor>> findClassesDerivingFrom(
String packageFilter,
String[] superClasses)
throws IOException, InvalidAttributeValueException, ClassFormatError {
packageFilter = packageFilter.replaceAll("\\.", "/"); //$NON-NLS-1$ //$NON-NLS-2$
- HashMap<String, ArrayList<IClass>> mClassesFound = new HashMap<String, ArrayList<IClass>>();
+ HashMap<String, ArrayList<IClassDescriptor>> mClassesFound =
+ new HashMap<String, ArrayList<IClassDescriptor>>();
for (String className : superClasses) {
- mClassesFound.put(className, new ArrayList<IClass>());
+ mClassesFound.put(className, new ArrayList<IClassDescriptor>());
}
// create streams to read the intermediary archive
@@ -415,7 +420,7 @@
* @param className the fully-qualified name of the class to return.
* @throws ClassNotFoundException
*/
- public IClass getClass(String className) throws ClassNotFoundException {
+ public IClassDescriptor getClass(String className) throws ClassNotFoundException {
try {
return new ClassWrapper(loadClass(className));
} catch (ClassNotFoundException e) {
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetData.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetData.java
new file mode 100644
index 0000000..60561ab
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetData.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.adt.sdk;
+
+import com.android.ide.eclipse.common.resources.IResourceRepository;
+import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
+import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
+import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
+import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors;
+import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors;
+import com.android.ide.eclipse.editors.resources.manager.ProjectResources;
+import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
+import com.android.layoutlib.api.ILayoutBridge;
+import com.android.sdklib.IAndroidTarget;
+
+import java.util.Hashtable;
+import java.util.Map;
+
+/**
+ * This class contains the data of an Android Target as loaded from the SDK.
+ */
+public class AndroidTargetData {
+
+ public final static int DESCRIPTOR_MANIFEST = 1;
+ public final static int DESCRIPTOR_LAYOUT = 2;
+ public final static int DESCRIPTOR_MENU = 3;
+ public final static int DESCRIPTOR_XML = 4;
+ public final static int DESCRIPTOR_RESOURCES = 5;
+ public final static int DESCRIPTOR_SEARCHABLE = 6;
+ public final static int DESCRIPTOR_PREFERENCES = 7;
+
+ public final static class LayoutBridge {
+ /** Link to the layout bridge */
+ public ILayoutBridge bridge;
+
+ public LoadStatus status = LoadStatus.LOADING;
+
+ public ClassLoader classLoader;
+ }
+
+ private final IAndroidTarget mTarget;
+
+ /**
+ * mAttributeValues is a map { key => list [ values ] }.
+ * The key for the map is "(element-xml-name,attribute-namespace:attribute-xml-local-name)".
+ * The attribute namespace prefix must be:
+ * - "android" for AndroidConstants.NS_RESOURCES
+ * - "xmlns" for the XMLNS URI.
+ *
+ * This is used for attributes that do not have a unique name, but still need to be populated
+ * with values in the UI. Uniquely named attributes have their values in {@link #mEnumValueMap}.
+ */
+ private final Hashtable<String, String[]> mAttributeValues = new Hashtable<String, String[]>();
+
+ private IResourceRepository mSystemResourceRepository;
+
+ private final AndroidManifestDescriptors mManifestDescriptors;
+ private final LayoutDescriptors mLayoutDescriptors;
+ private final MenuDescriptors mMenuDescriptors;
+ private final XmlDescriptors mXmlDescriptors;
+
+ private final Map<String, Map<String, Integer>> mEnumValueMap;
+
+ private final ProjectResources mFrameworkResources;
+ private final LayoutBridge mLayoutBridge;
+
+ private boolean mLayoutBridgeInit = false;
+
+ /**
+ * Creates an AndroidTargetData object.
+ */
+ AndroidTargetData(IAndroidTarget androidTarget,
+ IResourceRepository systemResourceRepository,
+ AndroidManifestDescriptors manifestDescriptors,
+ LayoutDescriptors layoutDescriptors,
+ MenuDescriptors menuDescriptors,
+ XmlDescriptors xmlDescriptors,
+ Map<String, Map<String, Integer>> enumValueMap,
+ String[] permissionValues,
+ String[] activityIntentActionValues,
+ String[] broadcastIntentActionValues,
+ String[] serviceIntentActionValues,
+ String[] intentCategoryValues,
+ ProjectResources resources,
+ LayoutBridge layoutBridge) {
+
+ mTarget = androidTarget;
+ mSystemResourceRepository = systemResourceRepository;
+ mManifestDescriptors = manifestDescriptors;
+ mLayoutDescriptors = layoutDescriptors;
+ mMenuDescriptors = menuDescriptors;
+ mXmlDescriptors = xmlDescriptors;
+ mEnumValueMap = enumValueMap;
+ mFrameworkResources = resources;
+ mLayoutBridge = layoutBridge;
+
+ setPermissions(permissionValues);
+ setIntentFilterActionsAndCategories(activityIntentActionValues, broadcastIntentActionValues,
+ serviceIntentActionValues, intentCategoryValues);
+ }
+
+ public IResourceRepository getSystemResources() {
+ return mSystemResourceRepository;
+ }
+
+ /**
+ * Returns an {@link IDescriptorProvider} from a given Id.
+ * The Id can be one of {@link #DESCRIPTOR_MANIFEST}, {@link #DESCRIPTOR_LAYOUT},
+ * {@link #DESCRIPTOR_MENU}, or {@link #DESCRIPTOR_XML}.
+ * All other values will throw an {@link IllegalArgumentException}.
+ */
+ public IDescriptorProvider getDescriptorProvider(int descriptorId) {
+ switch (descriptorId) {
+ case DESCRIPTOR_MANIFEST:
+ return mManifestDescriptors;
+ case DESCRIPTOR_LAYOUT:
+ return mLayoutDescriptors;
+ case DESCRIPTOR_MENU:
+ return mMenuDescriptors;
+ case DESCRIPTOR_XML:
+ return mXmlDescriptors;
+ case DESCRIPTOR_RESOURCES:
+ // FIXME: since it's hard-coded the Resources Descriptors are not platform dependent.
+ return ResourcesDescriptors.getInstance();
+ case DESCRIPTOR_PREFERENCES:
+ return mXmlDescriptors.getPreferencesProvider();
+ case DESCRIPTOR_SEARCHABLE:
+ return mXmlDescriptors.getSearchableProvider();
+ default :
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Returns the manifest descriptors.
+ */
+ public AndroidManifestDescriptors getManifestDescriptors() {
+ return mManifestDescriptors;
+ }
+
+ /**
+ * Returns the layout Descriptors.
+ */
+ public LayoutDescriptors getLayoutDescriptors() {
+ return mLayoutDescriptors;
+ }
+
+ /**
+ * Returns the menu descriptors.
+ */
+ public MenuDescriptors getMenuDescriptors() {
+ return mMenuDescriptors;
+ }
+
+ /**
+ * Returns the XML descriptors
+ */
+ public XmlDescriptors getXmlDescriptors() {
+ return mXmlDescriptors;
+ }
+
+ /**
+ * Returns this list of possible values for an XML attribute.
+ * <p/>This should only be called for attributes for which possible values depend on the
+ * parent element node.
+ * <p/>For attributes that have the same values no matter the parent node, use
+ * {@link #getEnumValueMap()}.
+ * @param elementName the name of the element containing the attribute.
+ * @param attributeName the name of the attribute
+ * @return an array of String with the possible values, or <code>null</code> if no values were
+ * found.
+ */
+ public String[] getAttributeValues(String elementName, String attributeName) {
+ String key = String.format("(%1$s,%2$s)", elementName, attributeName); //$NON-NLS-1$
+ return mAttributeValues.get(key);
+ }
+
+ /**
+ * Returns this list of possible values for an XML attribute.
+ * <p/>This should only be called for attributes for which possible values depend on the
+ * parent and great-grand-parent element node.
+ * <p/>The typical example of this is for the 'name' attribute under
+ * activity/intent-filter/action
+ * <p/>For attributes that have the same values no matter the parent node, use
+ * {@link #getEnumValueMap()}.
+ * @param elementName the name of the element containing the attribute.
+ * @param attributeName the name of the attribute
+ * @param greatGrandParentElementName the great-grand-parent node.
+ * @return an array of String with the possible values, or <code>null</code> if no values were
+ * found.
+ */
+ public String[] getAttributeValues(String elementName, String attributeName,
+ String greatGrandParentElementName) {
+ if (greatGrandParentElementName != null) {
+ String key = String.format("(%1$s,%2$s,%3$s)", //$NON-NLS-1$
+ greatGrandParentElementName, elementName, attributeName);
+ String[] values = mAttributeValues.get(key);
+ if (values != null) {
+ return values;
+ }
+ }
+
+ return getAttributeValues(elementName, attributeName);
+ }
+
+ /**
+ * Returns the enum values map.
+ * <p/>The map defines the possible values for XML attributes. The key is the attribute name
+ * and the value is a map of (string, integer) in which the key (string) is the name of
+ * the value, and the Integer is the numerical value in the compiled binary XML files.
+ */
+ public Map<String, Map<String, Integer>> getEnumValueMap() {
+ return mEnumValueMap;
+ }
+
+ /**
+ * Returns the {@link ProjectResources} containing the Framework Resources.
+ */
+ public ProjectResources getFrameworkResources() {
+ return mFrameworkResources;
+ }
+
+ /**
+ * Returns a {@link LayoutBridge} object possibly containing a {@link ILayoutBridge} object.
+ * <p/>If {@link LayoutBridge#bridge} is <code>null</code>, {@link LayoutBridge#status} will
+ * contain the reason (either {@link LoadStatus#LOADING} or {@link LoadStatus#FAILED}).
+ * <p/>Valid {@link ILayoutBridge} objects are always initialized before being returned.
+ */
+ public synchronized LayoutBridge getLayoutBridge() {
+ if (mLayoutBridgeInit == false && mLayoutBridge.bridge != null) {
+ mLayoutBridge.bridge.init(mTarget.getPath(IAndroidTarget.FONTS),
+ getEnumValueMap());
+ mLayoutBridgeInit = true;
+ }
+ return mLayoutBridge;
+ }
+
+ /**
+ * Sets the permission values
+ * @param permissionValues the list of permissions
+ */
+ private void setPermissions(String[] permissionValues) {
+ setValues("(uses-permission,android:name)", permissionValues); //$NON-NLS-1$
+ setValues("(application,android:permission)", permissionValues); //$NON-NLS-1$
+ setValues("(activity,android:permission)", permissionValues); //$NON-NLS-1$
+ setValues("(receiver,android:permission)", permissionValues); //$NON-NLS-1$
+ setValues("(service,android:permission)", permissionValues); //$NON-NLS-1$
+ setValues("(provider,android:permission)", permissionValues); //$NON-NLS-1$
+ }
+
+ private void setIntentFilterActionsAndCategories(String[] activityIntentActions,
+ String[] broadcastIntentActions, String[] serviceIntentActions,
+ String[] intentCategoryValues) {
+ setValues("(activity,action,android:name)", activityIntentActions); //$NON-NLS-1$
+ setValues("(receiver,action,android:name)", broadcastIntentActions); //$NON-NLS-1$
+ setValues("(service,action,android:name)", serviceIntentActions); //$NON-NLS-1$
+ setValues("(category,android:name)", intentCategoryValues); //$NON-NLS-1$
+ }
+
+ /**
+ * Sets a (name, values) pair in the hash map.
+ * <p/>
+ * If the name is already present in the map, it is first removed.
+ * @param name the name associated with the values.
+ * @param values The values to add.
+ */
+ private void setValues(String name, String[] values) {
+ mAttributeValues.remove(name);
+ mAttributeValues.put(name, values);
+ }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/FrameworkResourceParser.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetParser.java
similarity index 68%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/FrameworkResourceParser.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetParser.java
index 703efcf..232b9e8 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/FrameworkResourceParser.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Eclipse Public License, Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,19 +14,29 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.resources;
+package com.android.ide.eclipse.adt.sdk;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData.LayoutBridge;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.resources.AttrsXmlParser;
import com.android.ide.eclipse.common.resources.DeclareStyleableInfo;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
+import com.android.ide.eclipse.common.resources.IResourceRepository;
import com.android.ide.eclipse.common.resources.ResourceItem;
import com.android.ide.eclipse.common.resources.ResourceType;
import com.android.ide.eclipse.common.resources.ViewClassInfo;
+import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
+import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
+import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors;
+import com.android.ide.eclipse.editors.resources.manager.ProjectResources;
+import com.android.ide.eclipse.editors.resources.manager.ResourceManager;
+import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
+import com.android.layoutlib.api.ILayoutBridge;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import java.io.BufferedReader;
@@ -34,10 +44,11 @@
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
+import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
-import java.net.MalformedURLException;
import java.net.URL;
+import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -48,7 +59,7 @@
import javax.management.InvalidAttributeValueException;
/**
- * Parser for the framework library.
+ * Parser for the platform data in an SDK.
* <p/>
* This gather the following information:
* <ul>
@@ -57,14 +68,16 @@
* <li></li>
* </ul>
*/
-public final class FrameworkResourceParser {
+public final class AndroidTargetParser {
private static final String TAG = "Framework Resource Parser";
+ private final IAndroidTarget mAndroidTarget;
/**
- * Creates a framework resource parser.
+ * Creates a platform data parser.
*/
- public FrameworkResourceParser() {
+ public AndroidTargetParser(IAndroidTarget platformTarget) {
+ mAndroidTarget = platformTarget;
}
/**
@@ -77,34 +90,29 @@
* @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
* @return True if the SDK path was valid and parsing has been attempted.
*/
- public boolean parse(String osSdkPath, FrameworkResourceManager resourceManager,
- IProgressMonitor monitor) {
- if (osSdkPath == null || osSdkPath.length() == 0) {
- return false;
- }
-
+ public IStatus run(IProgressMonitor monitor) {
try {
- SubMonitor progress = SubMonitor.convert(monitor, 100);
+ SubMonitor progress = SubMonitor.convert(monitor,
+ String.format("Parsing SDK %1$s", mAndroidTarget.getName()),
+ 120);
AndroidJarLoader classLoader =
- new AndroidJarLoader(osSdkPath + AndroidConstants.FN_FRAMEWORK_LIBRARY);
+ new AndroidJarLoader(mAndroidTarget.getPath(IAndroidTarget.ANDROID_JAR));
- progress.subTask("Preloading");
- preload(classLoader, progress.newChild(40));
- progress.setWorkRemaining(60);
+ preload(classLoader, progress.newChild(40, SubMonitor.SUPPRESS_NONE));
+ progress.setWorkRemaining(80);
if (progress.isCanceled()) {
- return false;
+ return Status.CANCEL_STATUS;
}
// get the resource Ids.
progress.subTask("Resource IDs");
- FrameworkResourceRepository systemResourceRepository = new FrameworkResourceRepository(
- collectResourceIds(classLoader));
+ IResourceRepository frameworkRepository = collectResourceIds(classLoader);
progress.worked(5);
if (progress.isCanceled()) {
- return false;
+ return Status.CANCEL_STATUS;
}
// get the permissions
@@ -113,56 +121,59 @@
progress.worked(5);
if (progress.isCanceled()) {
- return false;
+ return Status.CANCEL_STATUS;
}
- String osLibPath = osSdkPath + AndroidConstants.OS_SDK_LIBS_FOLDER;
-
// get the action and category values for the Intents.
progress.subTask("Intents");
ArrayList<String> activity_actions = new ArrayList<String>();
ArrayList<String> broadcast_actions = new ArrayList<String>();
ArrayList<String> service_actions = new ArrayList<String>();
ArrayList<String> categories = new ArrayList<String>();
- collectIntentFilterActionsAndCategories(osLibPath,
- activity_actions, broadcast_actions, service_actions, categories);
+ collectIntentFilterActionsAndCategories(activity_actions, broadcast_actions,
+ service_actions, categories);
progress.worked(5);
if (progress.isCanceled()) {
- return false;
+ return Status.CANCEL_STATUS;
}
- progress.subTask("Layouts");
+ // gather the attribute definition
+ progress.subTask("Attributes definitions");
AttrsXmlParser attrsXmlParser = new AttrsXmlParser(
- osSdkPath + AndroidConstants.OS_SDK_ATTRS_XML);
+ mAndroidTarget.getPath(IAndroidTarget.ATTRIBUTES));
attrsXmlParser.preload();
+ progress.subTask("Manifest definitions");
AttrsXmlParser attrsManifestXmlParser = new AttrsXmlParser(
- osSdkPath + AndroidConstants.OS_SDK_ATTRS_MANIFEST_XML,
+ mAndroidTarget.getPath(IAndroidTarget.MANIFEST_ATTRIBUTES),
attrsXmlParser);
attrsManifestXmlParser.preload();
Collection<ViewClassInfo> mainList = new ArrayList<ViewClassInfo>();
Collection<ViewClassInfo> groupList = new ArrayList<ViewClassInfo>();
- collectLayoutClasses(osLibPath, classLoader, attrsXmlParser, mainList, groupList,
+ // collect the layout/widgets classes
+ progress.subTask("Widgets and layouts");
+ collectLayoutClasses(classLoader, attrsXmlParser, mainList, groupList,
progress.newChild(40));
if (progress.isCanceled()) {
- return false;
+ return Status.CANCEL_STATUS;
}
ViewClassInfo[] layoutViewsInfo = mainList.toArray(new ViewClassInfo[mainList.size()]);
ViewClassInfo[] layoutGroupsInfo = groupList.toArray(
new ViewClassInfo[groupList.size()]);
+ // collect the preferences classes.
mainList.clear();
groupList.clear();
collectPreferenceClasses(classLoader, attrsXmlParser, mainList, groupList,
progress.newChild(5));
if (progress.isCanceled()) {
- return false;
+ return Status.CANCEL_STATUS;
}
ViewClassInfo[] preferencesInfo = mainList.toArray(new ViewClassInfo[mainList.size()]);
@@ -177,34 +188,77 @@
Map<String, Map<String, Integer>> enumValueMap = attrsXmlParser.getEnumFlagValues();
if (progress.isCanceled()) {
- return false;
+ return Status.CANCEL_STATUS;
}
- String docBaseUrl = getDocumentationBaseUrl(
- osSdkPath + AndroidConstants.OS_SDK_DOCS_FOLDER);
+ // From the information that was collected, create the pieces that will be put in
+ // the PlatformData object.
+ AndroidManifestDescriptors manifestDescriptors = new AndroidManifestDescriptors();
+ manifestDescriptors.updateDescriptors(manifestMap);
+ progress.worked(10);
- FrameworkResourceManager.getInstance().setResources(systemResourceRepository,
- layoutViewsInfo,
- layoutGroupsInfo,
- preferencesInfo,
- preferenceGroupsInfo,
- xmlMenuMap,
- xmlSearchableMap,
- manifestMap,
+ if (progress.isCanceled()) {
+ return Status.CANCEL_STATUS;
+ }
+
+ LayoutDescriptors layoutDescriptors = new LayoutDescriptors();
+ layoutDescriptors.updateDescriptors(layoutViewsInfo, layoutGroupsInfo);
+ progress.worked(10);
+
+ if (progress.isCanceled()) {
+ return Status.CANCEL_STATUS;
+ }
+
+ MenuDescriptors menuDescriptors = new MenuDescriptors();
+ menuDescriptors.updateDescriptors(xmlMenuMap);
+ progress.worked(10);
+
+ if (progress.isCanceled()) {
+ return Status.CANCEL_STATUS;
+ }
+
+ XmlDescriptors xmlDescriptors = new XmlDescriptors();
+ xmlDescriptors.updateDescriptors(xmlSearchableMap, preferencesInfo,
+ preferenceGroupsInfo);
+ progress.worked(10);
+
+ // load the framework resources.
+ ProjectResources resources = ResourceManager.getInstance().loadFrameworkResources(
+ mAndroidTarget);
+ progress.worked(10);
+
+ // now load the layout lib bridge
+ LayoutBridge layoutBridge = loadLayoutBridge();
+ progress.worked(10);
+
+ // and finally create the PlatformData with all that we loaded.
+ AndroidTargetData targetData = new AndroidTargetData(mAndroidTarget,
+ frameworkRepository,
+ manifestDescriptors,
+ layoutDescriptors,
+ menuDescriptors,
+ xmlDescriptors,
enumValueMap,
permissionValues,
activity_actions.toArray(new String[activity_actions.size()]),
broadcast_actions.toArray(new String[broadcast_actions.size()]),
service_actions.toArray(new String[service_actions.size()]),
categories.toArray(new String[categories.size()]),
- docBaseUrl);
+ resources,
+ layoutBridge);
+
+ Sdk.getCurrent().setTargetData(mAndroidTarget, targetData);
- return true;
+ return Status.OK_STATUS;
} catch (Exception e) {
AdtPlugin.logAndPrintError(e, TAG, "SDK parser failed"); //$NON-NLS-1$
+ AdtPlugin.printToConsole("SDK parser failed", e.getMessage());
+ return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, "SDK parser failed", e);
+ } finally {
+ if (monitor != null) {
+ monitor.done();
+ }
}
-
- return false;
}
/**
@@ -217,7 +271,9 @@
*/
private void preload(AndroidJarLoader classLoader, IProgressMonitor monitor) {
try {
- classLoader.preLoadClasses("" /* all classes */, monitor); //$NON-NLS-1$
+ classLoader.preLoadClasses("" /* all classes */, //$NON-NLS-1$
+ mAndroidTarget.getName(), // monitor task label
+ monitor);
} catch (InvalidAttributeValueException e) {
AdtPlugin.log(e, "Problem preloading classes"); //$NON-NLS-1$
} catch (IOException e) {
@@ -226,24 +282,27 @@
}
/**
- * Collects the resources IDs found in the SDK.
+ * Creates an IResourceRepository for the framework resources.
*
* @param classLoader The framework SDK jar classloader
* @return a map of the resources, or null if it failed.
*/
- private Map<ResourceType, List<ResourceItem>> collectResourceIds(
+ private IResourceRepository collectResourceIds(
AndroidJarLoader classLoader) {
try {
Class<?> r = classLoader.loadClass(AndroidConstants.CLASS_R);
if (r != null) {
- return parseRClass(r);
+ Map<ResourceType, List<ResourceItem>> map = parseRClass(r);
+ if (map != null) {
+ return new FrameworkResourceRepository(map);
+ }
}
} catch (ClassNotFoundException e) {
AdtPlugin.logAndPrintError(e, TAG,
"Collect resource IDs failed, class %1$s not found in %2$s", //$NON-NLS-1$
AndroidConstants.CLASS_R,
- classLoader.getSource());
+ mAndroidTarget.getPath(IAndroidTarget.ANDROID_JAR));
}
return null;
@@ -331,7 +390,7 @@
AdtPlugin.logAndPrintError(e, TAG,
"Collect permissions failed, class %1$s not found in %2$s", //$NON-NLS-1$
AndroidConstants.CLASS_MANIFEST_PERMISSION,
- classLoader.getSource());
+ mAndroidTarget.getPath(IAndroidTarget.ANDROID_JAR));
}
return new String[0];
@@ -347,13 +406,17 @@
* @param serviceActions the list which will receive the service action values.
* @param categories the list which will receive the category values.
*/
- private void collectIntentFilterActionsAndCategories(String osLibPath,
- ArrayList<String> activityActions, ArrayList<String> broadcastActions,
+ private void collectIntentFilterActionsAndCategories(ArrayList<String> activityActions,
+ ArrayList<String> broadcastActions,
ArrayList<String> serviceActions, ArrayList<String> categories) {
- collectValues(osLibPath + "activity_actions.txt" , activityActions);
- collectValues(osLibPath + "broadcast_actions.txt" , broadcastActions);
- collectValues(osLibPath + "service_actions.txt" , serviceActions);
- collectValues(osLibPath + "categories.txt" , categories);
+ collectValues(mAndroidTarget.getPath(IAndroidTarget.ACTIONS_ACTIVITY),
+ activityActions);
+ collectValues(mAndroidTarget.getPath(IAndroidTarget.ACTIONS_BROADCAST),
+ broadcastActions);
+ collectValues(mAndroidTarget.getPath(IAndroidTarget.ACTIONS_SERVICE),
+ serviceActions);
+ collectValues(mAndroidTarget.getPath(IAndroidTarget.CATEGORIES),
+ categories);
}
/**
@@ -400,21 +463,21 @@
* Collects all layout classes information from the class loader and the
* attrs.xml and sets the corresponding structures in the resource manager.
*
- * @param osLibPath The OS path to the SDK tools/lib folder, ending with a separator.
- * @param classLoader The framework SDK jar classloader
+ * @param classLoader The framework SDK jar classloader in case we cannot get the widget from
+ * the platform directly
* @param attrsXmlParser The parser of the attrs.xml file
* @param mainList the Collection to receive the main list of {@link ViewClassInfo}.
* @param groupList the Collection to receive the group list of {@link ViewClassInfo}.
* @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
*/
- private void collectLayoutClasses(String osLibPath,
- AndroidJarLoader classLoader,
+ private void collectLayoutClasses(AndroidJarLoader classLoader,
AttrsXmlParser attrsXmlParser,
Collection<ViewClassInfo> mainList, Collection<ViewClassInfo> groupList,
IProgressMonitor monitor) {
LayoutParamsParser ldp = null;
try {
- WidgetListLoader loader = new WidgetListLoader(osLibPath + "widgets.txt");
+ WidgetClassLoader loader = new WidgetClassLoader(
+ mAndroidTarget.getPath(IAndroidTarget.WIDGETS));
if (loader.parseWidgetList(monitor)) {
ldp = new LayoutParamsParser(loader, attrsXmlParser);
}
@@ -465,12 +528,13 @@
}
} catch (NoClassDefFoundError e) {
AdtPlugin.logAndPrintError(e, TAG,
- "Collect preferences failed, class %1$s not found in %2$s", //$NON-NLS-1$
+ "Collect preferences failed, class %1$s not found in %2$s",
e.getMessage(),
classLoader.getSource());
} catch (Throwable e) {
AdtPlugin.log(e, "Android Framework Parser: failed to collect preference classes"); //$NON-NLS-1$
- AdtPlugin.printErrorToConsole("Android Framework Parser", "failed to collect preference classes");
+ AdtPlugin.printErrorToConsole("Android Framework Parser",
+ "failed to collect preference classes");
}
}
@@ -537,40 +601,51 @@
}
/**
- * Returns the URL to the local documentation.
- * Can return null if no documentation is found in the current SDK.
- *
- * @param osDocsPath Path to the documentation folder in the current SDK.
- * The folder may not actually exist.
- * @return A file:// URL on the local documentation folder if it exists or null.
+ * Loads the layout bridge from the dynamically loaded layoutlib.jar
*/
- private String getDocumentationBaseUrl(String osDocsPath) {
- File f = new File(osDocsPath);
+ private LayoutBridge loadLayoutBridge() {
+ LayoutBridge layoutBridge = new LayoutBridge();
- if (f.isDirectory()) {
- try {
- // Note: to create a file:// URL, one would typically use something like
- // f.toURI().toURL().toString(). However this generates a broken path on
- // Windows, namely "C:\\foo" is converted to "file:/C:/foo" instead of
- // "file:///C:/foo" (i.e. there should be 3 / after "file:"). So we'll
- // do the correct thing manually.
+ try {
+ // get the URL for the file.
+ File f = new File(mAndroidTarget.getPath(IAndroidTarget.LAYOUT_LIB));
+ if (f.isFile() == false) {
+ AdtPlugin.log(IStatus.ERROR, "layoutlib.jar is missing!"); //$NON-NLS-1$
+ } else {
+ URL url = f.toURL();
- String path = f.getAbsolutePath();
- if (File.separatorChar != '/') {
- path = path.replace(File.separatorChar, '/');
+ // create a class loader. Because this jar reference interfaces
+ // that are in the editors plugin, it's important to provide
+ // a parent class loader.
+ layoutBridge.classLoader = new URLClassLoader(new URL[] { url },
+ this.getClass().getClassLoader());
+
+ // load the class
+ Class<?> clazz = layoutBridge.classLoader.loadClass(AndroidConstants.CLASS_BRIDGE);
+ if (clazz != null) {
+ // instantiate an object of the class.
+ Constructor<?> constructor = clazz.getConstructor();
+ if (constructor != null) {
+ Object bridge = constructor.newInstance();
+ if (bridge instanceof ILayoutBridge) {
+ layoutBridge.bridge = (ILayoutBridge)bridge;
+ }
+ }
}
- // For some reason the URL class doesn't add the mandatory "//" after
- // the "file:" protocol name, so it has to be hacked into the path.
- URL url = new URL("file", null, "//" + path); //$NON-NLS-1$ //$NON-NLS-2$
- String result = url.toString();
- return result;
- } catch (MalformedURLException e) {
- // ignore malformed URLs
+ if (layoutBridge.bridge == null) {
+ layoutBridge.status = LoadStatus.FAILED;
+ AdtPlugin.log(IStatus.ERROR, "Failed to load " + AndroidConstants.CLASS_BRIDGE); //$NON-NLS-1$
+ } else {
+ layoutBridge.status = LoadStatus.LOADED;
+ }
}
+ } catch (Throwable t) {
+ layoutBridge.status = LoadStatus.FAILED;
+ // log the error.
+ AdtPlugin.log(t, "Failed to load the LayoutLib");
}
-
- return null;
+
+ return layoutBridge;
}
-
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/FrameworkResourceRepository.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/FrameworkResourceRepository.java
similarity index 92%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/FrameworkResourceRepository.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/FrameworkResourceRepository.java
index 19a7de3..f4b10df 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/FrameworkResourceRepository.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/FrameworkResourceRepository.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.resources;
+package com.android.ide.eclipse.adt.sdk;
import com.android.ide.eclipse.common.resources.IResourceRepository;
import com.android.ide.eclipse.common.resources.ResourceItem;
@@ -26,9 +26,9 @@
/**
* Implementation of the {@link IResourceRepository} interface to hold the system resource Ids
- * parsed by {@link FrameworkResourceParser}.
+ * parsed by {@link AndroidTargetParser}.
*/
-public final class FrameworkResourceRepository implements IResourceRepository {
+final class FrameworkResourceRepository implements IResourceRepository {
private Map<ResourceType, List<ResourceItem>> mResourcesMap;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/IAndroidLoader.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/IAndroidClassLoader.java
similarity index 77%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/IAndroidLoader.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/IAndroidClassLoader.java
index f0f48ca..50d319e 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/IAndroidLoader.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/IAndroidClassLoader.java
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.resources;
-
-import com.android.ide.eclipse.adt.resources.LayoutParamsParser.IClass;
+package com.android.ide.eclipse.adt.sdk;
import java.io.IOException;
import java.util.ArrayList;
@@ -28,7 +26,25 @@
* Classes which implements this interface provide methods to access framework resource
* data loaded from the SDK.
*/
-public interface IAndroidLoader {
+public interface IAndroidClassLoader {
+
+ /**
+ * Classes which implement this interface provide methods to describe a class.
+ */
+ public interface IClassDescriptor {
+
+ String getCanonicalName();
+
+ IClassDescriptor getSuperclass();
+
+ String getSimpleName();
+
+ IClassDescriptor getEnclosingClass();
+
+ IClassDescriptor[] getDeclaredClasses();
+
+ boolean isInstantiable();
+ }
/**
* Finds and loads all classes that derive from a given set of super classes.
@@ -43,7 +59,7 @@
* @throws InvalidAttributeValueException
* @throws ClassFormatError
*/
- public HashMap<String, ArrayList<IClass>> findClassesDerivingFrom(
+ public HashMap<String, ArrayList<IClassDescriptor>> findClassesDerivingFrom(
String rootPackage, String[] superClasses)
throws IOException, InvalidAttributeValueException, ClassFormatError;
@@ -52,7 +68,7 @@
* @param className the fully-qualified name of the class to return.
* @throws ClassNotFoundException
*/
- public IClass getClass(String className) throws ClassNotFoundException;
+ public IClassDescriptor getClass(String className) throws ClassNotFoundException;
/**
* Returns a string indicating the source of the classes, typically for debugging
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/LayoutParamsParser.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/LayoutParamsParser.java
similarity index 82%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/LayoutParamsParser.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/LayoutParamsParser.java
index ee71b60..dc600d7 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/LayoutParamsParser.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/LayoutParamsParser.java
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.resources;
+package com.android.ide.eclipse.adt.sdk;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.IAndroidClassLoader.IClassDescriptor;
import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.CommonPlugin;
import com.android.ide.eclipse.common.resources.AttrsXmlParser;
import com.android.ide.eclipse.common.resources.ViewClassInfo;
import com.android.ide.eclipse.common.resources.ViewClassInfo.LayoutParamsInfo;
@@ -52,23 +53,10 @@
public class LayoutParamsParser {
/**
- * Classes which implement this interface provide methods to describe a class.
+ * Class extending {@link ViewClassInfo} by adding the notion of instantiability.
+ * {@link LayoutParamsParser#getViews()} and {@link LayoutParamsParser#getGroups()} should
+ * only return classes that can be instantiated.
*/
- public interface IClass {
-
- public String getCanonicalName();
-
- public IClass getSuperclass();
-
- public String getSimpleName();
-
- public IClass getEnclosingClass();
-
- public IClass[] getDeclaredClasses();
-
- public boolean isInstantiable();
- }
-
final static class ExtViewClassInfo extends ViewClassInfo {
private boolean mIsInstantiable;
@@ -87,16 +75,16 @@
/* Note: protected members/methods are overridden in unit tests */
/** Reference to android.view.View */
- protected IClass mTopViewClass;
+ protected IClassDescriptor mTopViewClass;
/** Reference to android.view.ViewGroup */
- protected IClass mTopGroupClass;
+ protected IClassDescriptor mTopGroupClass;
/** Reference to android.view.ViewGroup$LayoutParams */
- protected IClass mTopLayoutParamsClass;
+ protected IClassDescriptor mTopLayoutParamsClass;
/** Input list of all classes deriving from android.view.View */
- protected ArrayList<IClass> mViewList;
+ protected ArrayList<IClassDescriptor> mViewList;
/** Input list of all classes deriving from android.view.ViewGroup */
- protected ArrayList<IClass> mGroupList;
+ protected ArrayList<IClassDescriptor> mGroupList;
/** Output map of FQCN => info on View classes */
protected TreeMap<String, ExtViewClassInfo> mViewMap;
@@ -109,14 +97,14 @@
protected AttrsXmlParser mAttrsXmlParser;
/** The android.jar class loader */
- protected IAndroidLoader mClassLoader;
+ protected IAndroidClassLoader mClassLoader;
/**
* Instantiate a new LayoutParamsParser.
* @param classLoader The android.jar class loader
* @param attrsXmlParser The parser of the attrs.xml file
*/
- public LayoutParamsParser(IAndroidLoader classLoader,
+ public LayoutParamsParser(IAndroidClassLoader classLoader,
AttrsXmlParser attrsXmlParser) {
mClassLoader = classLoader;
mAttrsXmlParser = attrsXmlParser;
@@ -135,8 +123,8 @@
/**
* TODO: doc here.
* <p/>
- * Note: on output we should have NO dependency on IClass, otherwise we wouldn't be able
- * to unload the class loader later.
+ * Note: on output we should have NO dependency on {@link IClassDescriptor},
+ * otherwise we wouldn't be able to unload the class loader later.
* <p/>
* Note on Vocabulary: FQCN=Fully Qualified Class Name (e.g. "my.package.class$innerClass")
* @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
@@ -168,8 +156,8 @@
if (paramsClassName != null) {
superClasses[2] = paramsClassName;
}
- HashMap<String, ArrayList<IClass>> found = mClassLoader.findClassesDerivingFrom(
- "android.", superClasses);
+ HashMap<String, ArrayList<IClassDescriptor>> found =
+ mClassLoader.findClassesDerivingFrom("android.", superClasses);
mTopViewClass = mClassLoader.getClass(rootClassName);
mTopGroupClass = mClassLoader.getClass(groupClassName);
if (paramsClassName != null) {
@@ -196,26 +184,26 @@
progress.setWorkRemaining(mGroupList.size() + mViewList.size());
- for (IClass groupChild : mGroupList) {
+ for (IClassDescriptor groupChild : mGroupList) {
addGroup(groupChild);
progress.worked(1);
}
- for (IClass viewChild : mViewList) {
+ for (IClassDescriptor viewChild : mViewList) {
if (viewChild != mTopGroupClass) {
addView(viewChild);
}
progress.worked(1);
}
} catch (ClassNotFoundException e) {
- CommonPlugin.log(e, "Problem loading class %1$s or %2$s", //$NON-NLS-1$
+ AdtPlugin.log(e, "Problem loading class %1$s or %2$s", //$NON-NLS-1$
rootClassName, groupClassName);
} catch (InvalidAttributeValueException e) {
- CommonPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
+ AdtPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
} catch (ClassFormatError e) {
- CommonPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
+ AdtPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
} catch (IOException e) {
- CommonPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
+ AdtPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
}
}
@@ -223,7 +211,7 @@
* Parses a View class and adds a ExtViewClassInfo for it in mViewMap.
* It calls itself recursively to handle super classes which are also Views.
*/
- private ExtViewClassInfo addView(IClass viewClass) {
+ private ExtViewClassInfo addView(IClassDescriptor viewClass) {
String fqcn = viewClass.getCanonicalName();
if (mViewMap.containsKey(fqcn)) {
return mViewMap.get(fqcn);
@@ -238,7 +226,7 @@
// All view classes derive from mTopViewClass by design.
// Do not lookup the super class for mTopViewClass itself.
if (viewClass.equals(mTopViewClass) == false) {
- IClass superClass = viewClass.getSuperclass();
+ IClassDescriptor superClass = viewClass.getSuperclass();
ExtViewClassInfo superClassInfo = addView(superClass);
info.setSuperClass(superClassInfo);
}
@@ -251,7 +239,7 @@
* Parses a ViewGroup class and adds a ExtViewClassInfo for it in mGroupMap.
* It calls itself recursively to handle super classes which are also ViewGroups.
*/
- private ExtViewClassInfo addGroup(IClass groupClass) {
+ private ExtViewClassInfo addGroup(IClassDescriptor groupClass) {
String fqcn = groupClass.getCanonicalName();
if (mGroupMap.containsKey(fqcn)) {
return mGroupMap.get(fqcn);
@@ -265,7 +253,7 @@
// android.view.View (i.e. mTopViewClass here). So the only group that can have View as
// its super class is the ViewGroup base class and we don't try to resolve it since groups
// are loaded before views.
- IClass superClass = groupClass.getSuperclass();
+ IClassDescriptor superClass = groupClass.getSuperclass();
// Assertion: at this point, we should have
// superClass != mTopViewClass || fqcn.equals(AndroidConstants.CLASS_VIEWGROUP);
@@ -291,15 +279,15 @@
*
* @return The {@link LayoutParamsInfo} for the ViewGroup class or null.
*/
- private LayoutParamsInfo addLayoutParams(IClass groupClass) {
+ private LayoutParamsInfo addLayoutParams(IClassDescriptor groupClass) {
// Is there a LayoutParams in this group class?
- IClass layoutParamsClass = findLayoutParams(groupClass);
+ IClassDescriptor layoutParamsClass = findLayoutParams(groupClass);
// if there's no layout data in the group class, link to the one from the
// super class.
if (layoutParamsClass == null) {
- for (IClass superClass = groupClass.getSuperclass();
+ for (IClassDescriptor superClass = groupClass.getSuperclass();
layoutParamsClass == null &&
superClass != null &&
superClass.equals(mTopViewClass) == false;
@@ -319,7 +307,7 @@
* Parses a LayoutParams class and returns a LayoutParamsInfo object for it.
* It calls itself recursively to handle the super class of the LayoutParams.
*/
- private LayoutParamsInfo getLayoutParamsInfo(IClass layoutParamsClass) {
+ private LayoutParamsInfo getLayoutParamsInfo(IClassDescriptor layoutParamsClass) {
String fqcn = layoutParamsClass.getCanonicalName();
LayoutParamsInfo layoutParamsInfo = mLayoutParamsMap.get(fqcn);
@@ -330,7 +318,7 @@
// Find the link on the LayoutParams super class
LayoutParamsInfo superClassInfo = null;
if (layoutParamsClass.equals(mTopLayoutParamsClass) == false) {
- IClass superClass = layoutParamsClass.getSuperclass();
+ IClassDescriptor superClass = layoutParamsClass.getSuperclass();
superClassInfo = getLayoutParamsInfo(superClass);
}
@@ -355,9 +343,9 @@
* @param groupClass The ViewGroup derived class
* @return The Class of the inner LayoutParams or null if none is declared.
*/
- private IClass findLayoutParams(IClass groupClass) {
- IClass[] innerClasses = groupClass.getDeclaredClasses();
- for (IClass innerClass : innerClasses) {
+ private IClassDescriptor findLayoutParams(IClassDescriptor groupClass) {
+ IClassDescriptor[] innerClasses = groupClass.getDeclaredClasses();
+ for (IClassDescriptor innerClass : innerClasses) {
if (innerClass.getSimpleName().equals(AndroidConstants.CLASS_LAYOUTPARAMS)) {
return innerClass;
}
@@ -365,12 +353,16 @@
return null;
}
+ /**
+ * Computes and return a list of ViewClassInfo from a map by filtering out the class that
+ * cannot be instantiated.
+ */
private List<ViewClassInfo> getInstantiables(SortedMap<String, ExtViewClassInfo> map) {
Collection<ExtViewClassInfo> values = map.values();
ArrayList<ViewClassInfo> list = new ArrayList<ViewClassInfo>();
for (ExtViewClassInfo info : values) {
- if (info.mIsInstantiable) {
+ if (info.isInstantiable()) {
list.add(info);
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/LoadStatus.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/LoadStatus.java
new file mode 100644
index 0000000..6bf0272
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/LoadStatus.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.adt.sdk;
+
+/**
+ * Enum for loading status of various SDK parts.
+ */
+public enum LoadStatus {
+ LOADING, LOADED, FAILED;
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/Sdk.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/Sdk.java
new file mode 100644
index 0000000..3b9d10e
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/Sdk.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.adt.sdk;
+
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.project.internal.AndroidClasspathContainerInitializer;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.ISdkLog;
+import com.android.sdklib.SdkConstants;
+import com.android.sdklib.SdkManager;
+import com.android.sdklib.project.ProjectProperties;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * Central point to load, manipulate and deal with the Android SDK. Only one SDK can be used
+ * at the same time.
+ *
+ * To start using an SDK, call {@link #loadSdk(String)} which returns the instance of
+ * the Sdk object.
+ *
+ * To get the list of platforms present in the SDK, call {@link #getPlatforms()}.
+ * To get the list of add-ons present in the SDK, call {@link #getAddons()}.
+ *
+ */
+public class Sdk {
+ private final static String PROPERTY_PROJECT_TARGET = "androidTarget"; //$NON-NLS-1$
+
+ private static Sdk sCurrentSdk = null;
+
+ private final SdkManager mManager;
+ private final HashMap<IProject, IAndroidTarget> mProjectMap =
+ new HashMap<IProject, IAndroidTarget>();
+ private final HashMap<IAndroidTarget, AndroidTargetData> mTargetMap =
+ new HashMap<IAndroidTarget, AndroidTargetData>();
+ private final String mDocBaseUrl;
+
+ /**
+ * Loads an SDK and returns an {@link Sdk} object if success.
+ * @param sdkLocation the OS path to the SDK.
+ */
+ public static Sdk loadSdk(String sdkLocation) {
+ if (sCurrentSdk != null) {
+ // manual unload?
+ sCurrentSdk = null;
+ }
+
+ final ArrayList<String> logMessages = new ArrayList<String>();
+ ISdkLog log = new ISdkLog() {
+ public void error(String errorFormat, Object... arg) {
+ logMessages.add(String.format(errorFormat, arg));
+ }
+ public void warning(String warningFormat, Object... arg) {
+ logMessages.add(String.format(warningFormat, arg));
+ }
+ };
+
+ // get an SdkManager object for the location
+ SdkManager manager = SdkManager.createManager(sdkLocation, log);
+ if (manager != null) {
+ sCurrentSdk = new Sdk(manager);
+ return sCurrentSdk;
+ } else {
+ StringBuilder sb = new StringBuilder("Error Loading the SDK:\n");
+ for (String msg : logMessages) {
+ sb.append('\n');
+ sb.append(msg);
+ }
+ AdtPlugin.displayError("Android SDK", sb.toString());
+ }
+ return null;
+ }
+
+ /**
+ * Returns the current {@link Sdk} object.
+ */
+ public static Sdk getCurrent() {
+ return sCurrentSdk;
+ }
+
+ /**
+ * Returns the URL to the local documentation.
+ * Can return null if no documentation is found in the current SDK.
+ *
+ * @return A file:// URL on the local documentation folder if it exists or null.
+ */
+ public String getDocumentationBaseUrl() {
+ return mDocBaseUrl;
+ }
+
+ /**
+ * Returns the list of targets that are available in the SDK.
+ */
+ public IAndroidTarget[] getTargets() {
+ return mManager.getTargets();
+ }
+
+ /**
+ * Returns a target from a hash that was generated by {@link IAndroidTarget#hashString()}.
+ * @param hash the hash
+ */
+ public IAndroidTarget getTargetFromHashString(String hash) {
+ return mManager.getTargetFromHashString(hash);
+ }
+
+ /**
+ * Associates an {@link IProject} and an {@link IAndroidTarget}.
+ */
+ public void setProject(IProject project, IAndroidTarget target) {
+ synchronized (mProjectMap) {
+ // look for the current target of the project
+ IAndroidTarget previousTarget = mProjectMap.get(project);
+
+ if (target != previousTarget) {
+ // save the target hash string in the project persistent property
+ setProjectTargetHashString(project, target.hashString());
+
+ // put it in a local map for easy access.
+ mProjectMap.put(project, target);
+
+ // recompile the project if needed.
+ IJavaProject javaProject = JavaCore.create(project);
+ AndroidClasspathContainerInitializer.updateProjects(
+ new IJavaProject[] { javaProject });
+ }
+ }
+ }
+
+ /**
+ * Returns the {@link IAndroidTarget} object associated with the given {@link IProject}.
+ */
+ public IAndroidTarget getTarget(IProject project) {
+ synchronized (mProjectMap) {
+ IAndroidTarget target = mProjectMap.get(project);
+ if (target == null) {
+ // get the value from the project persistent property.
+ String targetHashString = getProjectTargetHashString(project);
+
+ if (targetHashString != null) {
+ target = mManager.getTargetFromHashString(targetHashString);
+ }
+ }
+
+ return target;
+ }
+ }
+
+ /**
+ * Returns the hash string uniquely identifying the target of a project. This methods reads
+ * the string from the project persistent preferences/properties.
+ * <p/>The string is equivalent to the return of {@link IAndroidTarget#hashString()}.
+ * @param project The project for which to return the target hash string.
+ * @return the hash string or null if the project does not have a target set.
+ */
+ public static String getProjectTargetHashString(IProject project) {
+ // load the default.properties from the project folder.
+ ProjectProperties properties = ProjectProperties.load(project.getLocation().toOSString());
+ if (properties == null) {
+ AdtPlugin.log(IStatus.ERROR, "Failed to load properties file for project '%s'",
+ project.getName());
+ return null;
+ }
+
+ return properties.getProperty(ProjectProperties.PROPERTY_TARGET);
+ }
+
+ /**
+ * Sets a target hash string in a project's persistent preferences/property storage.
+ * @param project The project in which to save the hash string.
+ * @param targetHashString The target hash string to save. This must be the result from
+ * {@link IAndroidTarget#hashString()}.
+ */
+ public static void setProjectTargetHashString(IProject project, String targetHashString) {
+ // because we don't want to erase other properties from default.properties, we first load
+ // them
+ ProjectProperties properties = ProjectProperties.load(project.getLocation().toOSString());
+ if (properties == null) {
+ // doesn't exist yet? we create it.
+ properties = ProjectProperties.create(project.getLocation().toOSString());
+ }
+
+ // add/change the target hash string.
+ properties.setProperty(ProjectProperties.PROPERTY_TARGET, targetHashString);
+
+ // and rewrite the file.
+ try {
+ properties.save();
+ } catch (IOException e) {
+ AdtPlugin.log(e, "Failed to save default.properties for project '%s'",
+ project.getName());
+ }
+ }
+ /**
+ * Return the {@link PlatformData} for a given {@link IAndroidTarget}.
+ */
+ public AndroidTargetData getTargetData(IAndroidTarget target) {
+ synchronized (mTargetMap) {
+ return mTargetMap.get(target);
+ }
+ }
+
+ private Sdk(SdkManager manager) {
+ mManager = manager;
+
+ // pre-compute some paths
+ mDocBaseUrl = getDocumentationBaseUrl(mManager.getLocation() +
+ SdkConstants.OS_SDK_DOCS_FOLDER);
+ }
+
+ void setTargetData(IAndroidTarget target, AndroidTargetData data) {
+ synchronized (mTargetMap) {
+ mTargetMap.put(target, data);
+ }
+ }
+
+ /**
+ * Returns the URL to the local documentation.
+ * Can return null if no documentation is found in the current SDK.
+ *
+ * @param osDocsPath Path to the documentation folder in the current SDK.
+ * The folder may not actually exist.
+ * @return A file:// URL on the local documentation folder if it exists or null.
+ */
+ private String getDocumentationBaseUrl(String osDocsPath) {
+ File f = new File(osDocsPath);
+
+ if (f.isDirectory()) {
+ try {
+ // Note: to create a file:// URL, one would typically use something like
+ // f.toURI().toURL().toString(). However this generates a broken path on
+ // Windows, namely "C:\\foo" is converted to "file:/C:/foo" instead of
+ // "file:///C:/foo" (i.e. there should be 3 / after "file:"). So we'll
+ // do the correct thing manually.
+
+ String path = f.getAbsolutePath();
+ if (File.separatorChar != '/') {
+ path = path.replace(File.separatorChar, '/');
+ }
+
+ // For some reason the URL class doesn't add the mandatory "//" after
+ // the "file:" protocol name, so it has to be hacked into the path.
+ URL url = new URL("file", null, "//" + path); //$NON-NLS-1$ //$NON-NLS-2$
+ String result = url.toString();
+ return result;
+ } catch (MalformedURLException e) {
+ // ignore malformed URLs
+ }
+ }
+
+ return null;
+ }
+
+}
+
+
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/WidgetListLoader.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/WidgetClassLoader.java
similarity index 90%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/WidgetListLoader.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/WidgetClassLoader.java
index c85a50e..8db09f2 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/WidgetListLoader.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/WidgetClassLoader.java
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.resources;
+package com.android.ide.eclipse.adt.sdk;
-import com.android.ide.eclipse.adt.resources.LayoutParamsParser.IClass;
import com.android.ide.eclipse.common.AndroidConstants;
import org.eclipse.core.runtime.IProgressMonitor;
@@ -42,18 +41,19 @@
* where code is a single letter (W for widget, L for layout, P for layout params), and class names
* are the fully qualified name of the classes.
*/
-public final class WidgetListLoader implements IAndroidLoader {
+public final class WidgetClassLoader implements IAndroidClassLoader {
/**
* Basic class containing the class descriptions found in the text file.
*/
- private final static class ClassDescriptor implements IClass {
+ private final static class ClassDescriptor implements IClassDescriptor {
private String mName;
private String mSimpleName;
private ClassDescriptor mSuperClass;
private ClassDescriptor mEnclosingClass;
- private final ArrayList<IClass> mDeclaredClasses = new ArrayList<IClass>();
+ private final ArrayList<IClassDescriptor> mDeclaredClasses =
+ new ArrayList<IClassDescriptor>();
private boolean mIsInstantiable = false;
ClassDescriptor(String fqcn) {
@@ -69,15 +69,15 @@
return mSimpleName;
}
- public IClass[] getDeclaredClasses() {
- return mDeclaredClasses.toArray(new IClass[mDeclaredClasses.size()]);
+ public IClassDescriptor[] getDeclaredClasses() {
+ return mDeclaredClasses.toArray(new IClassDescriptor[mDeclaredClasses.size()]);
}
private void addDeclaredClass(ClassDescriptor declaredClass) {
mDeclaredClasses.add(declaredClass);
}
- public IClass getEnclosingClass() {
+ public IClassDescriptor getEnclosingClass() {
return mEnclosingClass;
}
@@ -93,7 +93,7 @@
mName = enclosingClass.mName + "$" + mName.substring(enclosingClass.mName.length() + 1);
}
- public IClass getSuperclass() {
+ public IClassDescriptor getSuperclass() {
return mSuperClass;
}
@@ -147,7 +147,7 @@
* @param osFilePath the OS path of the file to load.
* @throws FileNotFoundException if the file is not found.
*/
- WidgetListLoader(String osFilePath) throws FileNotFoundException {
+ WidgetClassLoader(String osFilePath) throws FileNotFoundException {
mOsFilePath = osFilePath;
mReader = new BufferedReader(new FileReader(osFilePath));
}
@@ -301,20 +301,21 @@
* @throws InvalidAttributeValueException
* @throws ClassFormatError
*/
- public HashMap<String, ArrayList<IClass>> findClassesDerivingFrom(String rootPackage,
+ public HashMap<String, ArrayList<IClassDescriptor>> findClassesDerivingFrom(String rootPackage,
String[] superClasses) throws IOException, InvalidAttributeValueException,
ClassFormatError {
- HashMap<String, ArrayList<IClass>> map = new HashMap<String, ArrayList<IClass>>();
+ HashMap<String, ArrayList<IClassDescriptor>> map =
+ new HashMap<String, ArrayList<IClassDescriptor>>();
- ArrayList<IClass> list = new ArrayList<IClass>();
+ ArrayList<IClassDescriptor> list = new ArrayList<IClassDescriptor>();
list.addAll(mWidgetMap.values());
map.put(AndroidConstants.CLASS_VIEW, list);
- list = new ArrayList<IClass>();
+ list = new ArrayList<IClassDescriptor>();
list.addAll(mLayoutMap.values());
map.put(AndroidConstants.CLASS_VIEWGROUP, list);
- list = new ArrayList<IClass>();
+ list = new ArrayList<IClassDescriptor>();
list.addAll(mLayoutParamsMap.values());
map.put(AndroidConstants.CLASS_VIEWGROUP_LAYOUTPARAMS, list);
@@ -326,7 +327,7 @@
* @param className the fully-qualified name of the class to return.
* @throws ClassNotFoundException
*/
- public IClass getClass(String className) throws ClassNotFoundException {
+ public IClassDescriptor getClass(String className) throws ClassNotFoundException {
return mMap.get(className);
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/NewProjectCreationPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectCreationPage.java
similarity index 95%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/NewProjectCreationPage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectCreationPage.java
index d395905..8044bcb 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/NewProjectCreationPage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectCreationPage.java
@@ -20,11 +20,13 @@
* org.eclipse.jdt.internal.ui.wizards.JavaProjectWizardFirstPage
*/
-package com.android.ide.eclipse.adt.project.internal;
+package com.android.ide.eclipse.adt.wizards.newproject;
-import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestHelper;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdkuilib.SdkTargetSelector;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.resources.IProject;
@@ -120,6 +122,7 @@
private boolean mInternalActivityNameUpdate;
protected boolean mProjectNameModifiedByUser;
protected boolean mApplicationNameModifiedByUser;
+ private SdkTargetSelector mSdkTargetSelector;
/**
@@ -133,7 +136,9 @@
if (sCustomLocationOsPath == null ||
sCustomLocationOsPath.length() == 0 ||
!new File(sCustomLocationOsPath).isDirectory()) {
- sCustomLocationOsPath = AdtPlugin.getOsSdkSamplesFolder();
+ // FIXME location of samples is pretty much impossible here.
+ //sCustomLocationOsPath = AdtPlugin.getOsSdkSamplesFolder();
+ sCustomLocationOsPath = File.listRoots()[0].getAbsolutePath();
}
}
@@ -200,6 +205,11 @@
return mSourceFolder;
}
}
+
+ /** Returns the current sdk target or null if none has been selected yet. */
+ public IAndroidTarget getSdkTarget() {
+ return mSdkTargetSelector == null ? null : mSdkTargetSelector.getFirstSelected();
+ }
/**
* Overrides @DialogPage.setVisible(boolean) to put the focus in the project name when
@@ -232,15 +242,19 @@
createProjectNameGroup(composite);
createLocationGroup(composite);
+ createTargetGroup(composite);
createPropertiesGroup(composite);
// Update state the first time
enableLocationWidgets();
- setPageComplete(validatePage());
+
// Show description the first time
setErrorMessage(null);
setMessage(null);
setControl(composite);
+
+ // Validate. This will complain about the first empty field.
+ setPageComplete(validatePage());
}
/**
@@ -357,6 +371,33 @@
}
/**
+ * Creates the target group.
+ * It only contains an SdkTargetSelector.
+ */
+ private void createTargetGroup(Composite parent) {
+ Group group = new Group(parent, SWT.SHADOW_ETCHED_IN);
+ // Layout has 1 column
+ group.setLayout(new GridLayout());
+ group.setLayoutData(new GridData(GridData.FILL_BOTH));
+ group.setFont(parent.getFont());
+ group.setText("Target");
+
+ // get the targets from the sdk
+ IAndroidTarget[] targets = null;
+ if (Sdk.getCurrent() != null) {
+ targets = Sdk.getCurrent().getTargets();
+ }
+
+ mSdkTargetSelector = new SdkTargetSelector(group, targets, false /*multi-selection*/);
+ mSdkTargetSelector.setSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ setPageComplete(validatePage());
+ }
+ });
+ }
+
+ /**
* Display a directory browser and update the location path field with the selected path
*/
private void openDirectoryBrowser() {
@@ -755,6 +796,9 @@
status |= validateLocationPath(workspace);
}
if ((status & MSG_ERROR) == 0) {
+ status |= validateSdkTarget();
+ }
+ if ((status & MSG_ERROR) == 0) {
status |= validatePackageField();
}
if ((status & MSG_ERROR) == 0) {
@@ -894,6 +938,18 @@
}
/**
+ * Validates the sdk target choice.
+ *
+ * @return The wizard message type, one of MSG_ERROR, MSG_WARNING or MSG_NONE.
+ */
+ private int validateSdkTarget() {
+ if (getSdkTarget() == null) {
+ return setStatus("An SDK Target must be specified.", MSG_ERROR);
+ }
+ return MSG_NONE;
+ }
+
+ /**
* Validates the activity name field.
*
* @return The wizard message type, one of MSG_ERROR, MSG_WARNING or MSG_NONE.
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/NewProjectWizard.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectWizard.java
similarity index 94%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/NewProjectWizard.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectWizard.java
index a67f5ed..a582217 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/NewProjectWizard.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectWizard.java
@@ -14,12 +14,14 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.project.internal;
+package com.android.ide.eclipse.adt.wizards.newproject;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.project.AndroidNature;
import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
@@ -60,6 +62,7 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
+import java.util.Map.Entry;
/**
* A "New Android Project" Wizard.
@@ -81,6 +84,7 @@
private static final String PARAM_STRING_CONTENT = "STRING_CONTENT"; //$NON-NLS-1$
private static final String PARAM_IS_NEW_PROJECT = "IS_NEW_PROJECT"; //$NON-NLS-1$
private static final String PARAM_SRC_FOLDER = "SRC_FOLDER"; //$NON-NLS-1$
+ private static final String PARAM_SDK_TARGET = "SDK_TARGET"; //$NON-NLS-1$
private static final String PH_ACTIVITIES = "ACTIVITIES"; //$NON-NLS-1$
private static final String PH_INTENT_FILTERS = "INTENT_FILTERS"; //$NON-NLS-1$
@@ -223,13 +227,14 @@
final IProject project = workspace.getRoot().getProject(mMainPage.getProjectName());
final IProjectDescription description = workspace.newProjectDescription(project.getName());
- final Map<String, String> parameters = new HashMap<String, String>();
+ final Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put(PARAM_PROJECT, mMainPage.getProjectName());
parameters.put(PARAM_PACKAGE, mMainPage.getPackageName());
parameters.put(PARAM_APPLICATION, STRING_RSRC_PREFIX + STRING_APP_NAME);
parameters.put(PARAM_SDK_TOOLS_DIR, AdtPlugin.getOsSdkToolsFolder());
- parameters.put(PARAM_IS_NEW_PROJECT, Boolean.toString(mMainPage.isNewProject()));
+ parameters.put(PARAM_IS_NEW_PROJECT, mMainPage.isNewProject());
parameters.put(PARAM_SRC_FOLDER, mMainPage.getSourceFolder());
+ parameters.put(PARAM_SDK_TARGET, mMainPage.getSdkTarget());
if (mMainPage.isCreateActivity()) {
// An activity name can be of the form ".package.Class" or ".Class".
@@ -315,7 +320,7 @@
* to create or modify the project or if it is canceled by the user.
*/
private void createProjectAsync(IProject project, IProjectDescription description,
- IProgressMonitor monitor, Map<String, String> parameters,
+ IProgressMonitor monitor, Map<String, Object> parameters,
Map<String, String> stringDictionary)
throws InvocationTargetException {
monitor.beginTask("Create Android Project", 100);
@@ -330,7 +335,7 @@
// Create folders in the project if they don't already exist
addDefaultDirectories(project, AndroidConstants.WS_ROOT, DEFAULT_DIRECTORIES, monitor);
- String[] sourceFolder = new String[] { parameters.get(PARAM_SRC_FOLDER) };
+ String[] sourceFolder = new String[] { (String) parameters.get(PARAM_SRC_FOLDER) };
addDefaultDirectories(project, AndroidConstants.WS_ROOT, sourceFolder, monitor);
// Create the resource folders in the project if they don't already exist.
@@ -340,7 +345,7 @@
IJavaProject javaProject = JavaCore.create(project);
setupSourceFolder(javaProject, sourceFolder[0], monitor);
- if (Boolean.parseBoolean(parameters.get(PARAM_IS_NEW_PROJECT))) {
+ if (((Boolean) parameters.get(PARAM_IS_NEW_PROJECT)).booleanValue()) {
// Create files in the project if they don't already exist
addManifest(project, parameters, stringDictionary, monitor);
@@ -360,6 +365,8 @@
monitor);
}
+ Sdk.getCurrent().setProject(project, (IAndroidTarget) parameters.get(PARAM_SDK_TARGET));
+
// Fix the project to make sure all properties are as expected.
// Necessary for existing projects and good for new ones to.
ProjectHelper.fixProject(project);
@@ -409,7 +416,7 @@
* @throws IOException if the method fails to create the files in the
* project.
*/
- private void addManifest(IProject project, Map<String, String> parameters,
+ private void addManifest(IProject project, Map<String, Object> parameters,
Map<String, String> stringDictionary, IProgressMonitor monitor)
throws CoreException, IOException {
@@ -543,16 +550,16 @@
* project.
*/
private void addSampleCode(IProject project, String sourceFolder,
- Map<String, String> parameters, Map<String, String> stringDictionary,
+ Map<String, Object> parameters, Map<String, String> stringDictionary,
IProgressMonitor monitor) throws CoreException, IOException {
// create the java package directories.
IFolder pkgFolder = project.getFolder(sourceFolder);
- String packageName = parameters.get(PARAM_PACKAGE);
+ String packageName = (String) parameters.get(PARAM_PACKAGE);
// The PARAM_ACTIVITY key will be absent if no activity should be created,
// in which case activityName will be null.
- String activityName = parameters.get(PARAM_ACTIVITY);
- Map<String, String> java_activity_parameters = parameters;
+ String activityName = (String) parameters.get(PARAM_ACTIVITY);
+ Map<String, Object> java_activity_parameters = parameters;
if (activityName != null) {
if (activityName.indexOf('.') >= 0) {
// There are package names in the activity name. Transform packageName to add
@@ -564,7 +571,7 @@
// Also update the values used in the JAVA_FILE_TEMPLATE below
// (but not the ones from the manifest so don't change the caller's dictionary)
- java_activity_parameters = new HashMap<String, String>(parameters);
+ java_activity_parameters = new HashMap<String, Object>(parameters);
java_activity_parameters.put(PARAM_PACKAGE, packageName);
java_activity_parameters.put(PARAM_ACTIVITY, activityName);
}
@@ -665,7 +672,7 @@
* length.
*/
private void copyFile(String resourceFilename, IFile destFile,
- Map<String, String> parameters, IProgressMonitor monitor)
+ Map<String, Object> parameters, IProgressMonitor monitor)
throws CoreException, IOException {
// Read existing file.
@@ -692,13 +699,14 @@
* Replaces placeholders found in a string with values.
*
* @param str the string to search for placeholders.
- * @param parameters a map of <placeholder, Value> to search for in the
- * string
+ * @param parameters a map of <placeholder, Value> to search for in the string
* @return A new String object with the placeholder replaced by the values.
*/
- private String replaceParameters(String str, Map<String, String> parameters) {
- for (String key : parameters.keySet()) {
- str = str.replaceAll(key, parameters.get(key));
+ private String replaceParameters(String str, Map<String, Object> parameters) {
+ for (Entry<String, Object> entry : parameters.entrySet()) {
+ if (entry.getValue() instanceof String) {
+ str = str.replaceAll(entry.getKey(), (String) entry.getValue());
+ }
}
return str;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/AndroidConstants.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java
similarity index 72%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/AndroidConstants.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java
index 02cef2d..f3f7b79 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/AndroidConstants.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java
@@ -16,6 +16,8 @@
package com.android.ide.eclipse.common;
+import com.android.sdklib.SdkConstants;
+
import java.io.File;
/**
@@ -38,8 +40,11 @@
*
*/
public class AndroidConstants {
- /** The Editors Plugin ID */
- public static final String EDITORS_PLUGIN_ID = "com.android.ide.eclipse.editors"; // $NON-NLS-1$
+ /**
+ * The old Editors Plugin ID. It is still used in some places for compatibility.
+ * Please do not use for new features.
+ */
+ public static final String EDITORS_NAMESPACE = "com.android.ide.eclipse.editors"; // $NON-NLS-1$
/** Nature of android projects */
public final static String NATURE = "com.android.ide.eclipse.adt.AndroidNature"; //$NON-NLS-1$
@@ -72,6 +77,8 @@
public final static String EXT_JAR = "jar"; //$NON-NLS-1$
/** Extension of aidl files, i.e. "aidl" */
public final static String EXT_AIDL = "aidl"; //$NON-NLS-1$
+ /** Extension of native libraries, i.e. "so" */
+ public final static String EXT_NATIVE_LIB = "so"; //$NON-NLS-1$
private final static String DOT = "."; //$NON-NLS-1$
@@ -90,17 +97,8 @@
/** Name of the manifest file, i.e. "AndroidManifest.xml". */
public static final String FN_ANDROID_MANIFEST = "AndroidManifest.xml"; //$NON-NLS-1$
+ public static final String FN_PROJECT_AIDL = "project.aidl"; //$NON-NLS-1$
- /** Name of the framework library, i.e. "android.jar" */
- public static final String FN_FRAMEWORK_LIBRARY = "android.jar"; //$NON-NLS-1$
- /** Name of the layout attributes, i.e. "attrs.xml" */
- public static final String FN_ATTRS_XML = "attrs.xml"; //$NON-NLS-1$
- /** Name of the layout attributes, i.e. "attrs_manifest.xml" */
- public static final String FN_ATTRS_MANIFEST_XML = "attrs_manifest.xml"; //$NON-NLS-1$
- /** framework aidl import file */
- public static final String FN_FRAMEWORK_AIDL = "framework.aidl"; //$NON-NLS-1$
- /** layoutlib.jar file */
- public static final String FN_LAYOUTLIB_JAR = "layoutlib.jar"; //$NON-NLS-1$
/** dex.jar file */
public static final String FN_DX_JAR = "dx.jar"; //$NON-NLS-1$
/** Name of the android sources directory */
@@ -116,10 +114,6 @@
public final static String FN_CLASSES_DEX = "classes.dex"; //$NON-NLS-1$
/** Temporary packaged resources file name, i.e. "resources.ap_" */
public final static String FN_RESOURCES_AP_ = "resources.ap_"; //$NON-NLS-1$
- /** build properties file */
- public final static String FN_BUILD_PROP = "build.prop"; //$NON-NLS-1$
- /** plugin properties file */
- public final static String FN_PLUGIN_PROP = "plugin.prop"; //$NON-NLS-1$
public final static String FN_ADB = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ?
"adb.exe" : "adb"; //$NON-NLS-1$ //$NON-NLS-2$
@@ -136,15 +130,21 @@
public final static String FN_TRACEVIEW = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ?
"traceview.exe" : "traceview"; //$NON-NLS-1$ //$NON-NLS-2$
- /** Skin layout file */
- public final static String FN_LAYOUT = "layout";//$NON-NLS-1$
+ /** Folder Names for Android Projects . */
- /** Resources folder name, i.e. "res". */
+ /* Resources folder name, i.e. "res". */
public final static String FD_RESOURCES = "res"; //$NON-NLS-1$
/** Assets folder name, i.e. "assets" */
public final static String FD_ASSETS = "assets"; //$NON-NLS-1$
/** Default source folder name, i.e. "src" */
public final static String FD_SOURCES = "src"; //$NON-NLS-1$
+ /** Default native library folder name inside the project, i.e. "libs"
+ * While the folder inside the .apk is "lib", we call that one libs because
+ * that's what we use in ant for both .jar and .so and we need to make the 2 development ways
+ * compatible. */
+ public final static String FD_NATIVE_LIBS = "libs"; //$NON-NLS-1$
+ /** Native lib folder inside the APK: "lib" */
+ public final static String FD_APK_NATIVE_LIBS = "lib"; //$NON-NLS-1$
/** Default bin folder name, i.e. "bin" */
public final static String FD_BINARIES = "bin"; //$NON-NLS-1$
/** Default anim resource folder name, i.e. "anim" */
@@ -163,22 +163,6 @@
public final static String FD_XML = "xml"; //$NON-NLS-1$
/** Default raw resource folder name, i.e. "raw" */
public final static String FD_RAW = "raw"; //$NON-NLS-1$
- /** Name of the tools folder. */
- public final static String FD_TOOLS = "tools"; //$NON-NLS-1$
- /** Name of the libs folder. */
- public final static String FD_LIBS = "lib"; //$NON-NLS-1$
- /** Name of the docs folder. */
- public final static String FD_DOCS = "docs"; //$NON-NLS-1$
- /** Name of the images folder. */
- public final static String FD_IMAGES = "images"; //$NON-NLS-1$
- /** Name of the skins folder. */
- public final static String FD_SKINS = "skins"; //$NON-NLS-1$
- /** Name of the samples folder. */
- public final static String FD_SAMPLES = "samples"; //$NON-NLS-1$
- /** Name of the folder containing the default framework resources. */
- public final static String FD_DEFAULT_RES = "default"; //$NON-NLS-1$
- /** SDK font folder name, i.e. "fonts" */
- public final static String FD_FONTS = "fonts"; //$NON-NLS-1$
/** Absolute path of the workspace root, i.e. "/" */
public final static String WS_ROOT = WS_SEP;
@@ -190,57 +174,16 @@
public final static String WS_ASSETS = WS_SEP + FD_ASSETS;
/** Leaf of the javaDoc folder. Does not start with a separator. */
- public final static String WS_JAVADOC_FOLDER_LEAF = FD_DOCS + "/reference"; //$NON-NLS-1$
-
- /** Path of the documentation directory relative to the sdk folder.
- * This is an OS path, ending with a separator. */
- public final static String OS_SDK_DOCS_FOLDER = FD_DOCS + File.separator;
-
- /** Path of the tools directory relative to the sdk folder.
- * This is an OS path, ending with a separator. */
- public final static String OS_SDK_TOOLS_FOLDER = FD_TOOLS + File.separator;
+ public final static String WS_JAVADOC_FOLDER_LEAF = SdkConstants.FD_DOCS + "/reference"; //$NON-NLS-1$
/** Path of the samples directory relative to the sdk folder.
- * This is an OS path, ending with a separator. */
- public final static String OS_SDK_SAMPLES_FOLDER = FD_SAMPLES + File.separator;
-
- /** Path of the lib directory relative to the sdk folder.
- * This is an OS path, ending with a separator. */
- public final static String OS_SDK_LIBS_FOLDER =
- OS_SDK_TOOLS_FOLDER + FD_LIBS + File.separator;
-
- /** Path of the resources directory relative to the sdk folder.
- * This is an OS path, ending with a separator. */
- public final static String OS_SDK_RESOURCES_FOLDER =
- OS_SDK_LIBS_FOLDER + FD_RESOURCES + File.separator;
-
- /** Path of the resources directory relative to the sdk folder.
- * This is an OS path, ending with a separator. */
- public final static String OS_SDK_FONTS_FOLDER =
- OS_SDK_LIBS_FOLDER + FD_FONTS + File.separator;
-
- /** Path of the skin directory relative to the sdk folder.
- * This is an OS path, ending with a separator. */
- public final static String OS_SDK_SKINS_FOLDER =
- OS_SDK_LIBS_FOLDER + FD_IMAGES + File.separator + FD_SKINS + File.separator;
-
- /** Path of the attrs.xml file relative to the sdk folder. */
- public final static String OS_SDK_ATTRS_XML =
- OS_SDK_RESOURCES_FOLDER + File.separator + FD_DEFAULT_RES + File.separator +
- FD_VALUES + File.separator + FN_ATTRS_XML;
-
- /** Path of the attrs_manifest.xml file relative to the sdk folder. */
- public final static String OS_SDK_ATTRS_MANIFEST_XML =
- OS_SDK_RESOURCES_FOLDER + File.separator + FD_DEFAULT_RES + File.separator +
- FD_VALUES + File.separator + FN_ATTRS_MANIFEST_XML;
-
- /** Path of the layoutlib.jar file relative to the sdk folder. */
- public final static String OS_SDK_LIBS_LAYOUTLIB_JAR =
- OS_SDK_LIBS_FOLDER + FN_LAYOUTLIB_JAR;
+ * This is an OS path, ending with a separator.
+ * FIXME: remove once the NPW is fixed. */
+ public final static String OS_SDK_SAMPLES_FOLDER = SdkConstants.FD_SAMPLES + File.separator;
/** Path of the dx.jar file relative to the sdk folder. */
public final static String OS_SDK_LIBS_DX_JAR =
- OS_SDK_LIBS_FOLDER + FN_DX_JAR;
+ SdkConstants.OS_SDK_TOOLS_LIB_FOLDER + FN_DX_JAR;
/** Regexp for single dot */
public final static String RE_DOT = "\\."; //$NON-NLS-1$
@@ -255,17 +198,20 @@
/** Namespace pattern for the custom resource XML, i.e. "http://schemas.android.com/apk/res/%s" */
public final static String NS_CUSTOM_RESOURCES = "http://schemas.android.com/apk/res/%1$s"; //$NON-NLS-1$
+ /** The old common plug-in ID. Please do not use for new features. */
+ public static final String COMMON_PLUGIN_ID = "com.android.ide.eclipse.common"; //$NON-NLS-1$
+
/** aapt marker error. */
- public final static String MARKER_AAPT = CommonPlugin.PLUGIN_ID + ".aaptProblem"; //$NON-NLS-1$
+ public final static String MARKER_AAPT = COMMON_PLUGIN_ID + ".aaptProblem"; //$NON-NLS-1$
/** XML marker error. */
- public final static String MARKER_XML = CommonPlugin.PLUGIN_ID + ".xmlProblem"; //$NON-NLS-1$
+ public final static String MARKER_XML = COMMON_PLUGIN_ID + ".xmlProblem"; //$NON-NLS-1$
/** aidl marker error. */
- public final static String MARKER_AIDL = CommonPlugin.PLUGIN_ID + ".aidlProblem"; //$NON-NLS-1$
+ public final static String MARKER_AIDL = COMMON_PLUGIN_ID + ".aidlProblem"; //$NON-NLS-1$
/** android marker error */
- public final static String MARKER_ANDROID = CommonPlugin.PLUGIN_ID + ".androidProblem"; //$NON-NLS-1$
+ public final static String MARKER_ANDROID = COMMON_PLUGIN_ID + ".androidProblem"; //$NON-NLS-1$
/** Name for the "type" marker attribute */
public final static String MARKER_ATTR_TYPE = "android.type"; //$NON-NLS-1$
@@ -301,6 +247,7 @@
public final static String CLASS_PREFERENCES =
"android.preference." + CLASS_PREFERENCE_SCREEN; //$NON-NLS-1$
public final static String CLASS_PREFERENCEGROUP = "android.preference.PreferenceGroup"; //$NON-NLS-1$
+ public final static String CLASS_PARCELABLE = "android.os.Parcelable"; //$NON-NLS-1$
public final static String CLASS_BRIDGE = "com.android.layoutlib.bridge.Bridge"; //$NON-NLS-1$
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/EclipseUiHelper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/EclipseUiHelper.java
similarity index 95%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/EclipseUiHelper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/EclipseUiHelper.java
index 8dd8e60..6dc8562 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/EclipseUiHelper.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/EclipseUiHelper.java
@@ -53,7 +53,7 @@
try {
IViewPart part = page.showView(viewId,
null /* secondaryId */,
- activate ? page.VIEW_ACTIVATE : page.VIEW_VISIBLE);
+ activate ? IWorkbenchPage.VIEW_ACTIVATE : IWorkbenchPage.VIEW_VISIBLE);
} catch (PartInitException e) {
// ignore
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/Messages.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/Messages.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/Messages.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/Messages.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/SdkStatsHelper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/SdkStatsHelper.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/SdkStatsHelper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/SdkStatsHelper.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/StreamHelper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/StreamHelper.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/StreamHelper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/StreamHelper.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/messages.properties b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/messages.properties
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/messages.properties
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/messages.properties
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/preferences/UsagePreferencePage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/preferences/UsagePreferencePage.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/preferences/UsagePreferencePage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/preferences/UsagePreferencePage.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidManifestHelper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestHelper.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidManifestHelper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestHelper.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
similarity index 91%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
index 42f2a8b..cb98525 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
@@ -44,6 +44,7 @@
private final static String ATTRIBUTE_NAME = "name"; //$NON-NLS-1$
private final static String ATTRIBUTE_PROCESS = "process"; //$NON-NLS-$
private final static String ATTRIBUTE_DEBUGGABLE = "debuggable"; //$NON-NLS-$
+ private final static String ATTRIBUTE_MIN_SDK_VERSION = "minSdkVersion"; //$NON-NLS-$
private final static String NODE_MANIFEST = "manifest"; //$NON-NLS-1$
private final static String NODE_APPLICATION = "application"; //$NON-NLS-1$
private final static String NODE_ACTIVITY = "activity"; //$NON-NLS-1$
@@ -53,6 +54,7 @@
private final static String NODE_INTENT = "intent-filter"; //$NON-NLS-1$
private final static String NODE_ACTION = "action"; //$NON-NLS-1$
private final static String NODE_CATEGORY = "category"; //$NON-NLS-1$
+ private final static String NODE_USES_SDK = "uses-sdk"; //$NON-NLS-1$
private final static int LEVEL_MANIFEST = 0;
private final static int LEVEL_APPLICATION = 1;
@@ -77,6 +79,8 @@
private Set<String> mProcesses = null;
/** debuggable attribute value. If null, the attribute is not present. */
private Boolean mDebuggable = null;
+ /** API level requirement. if 0 the attribute was not present. */
+ private int mApiLevelRequirement = 0;
//--- temporary data/flags used during parsing
private IJavaProject mJavaProject;
@@ -142,12 +146,19 @@
}
/**
- * Returns the debuggable attribute value or null if it is not set.
+ * Returns the <code>debuggable</code> attribute value or null if it is not set.
*/
Boolean getDebuggable() {
return mDebuggable;
}
+ /**
+ * Returns the <code>minSdkVersion</code> attribute, or 0 if it's not set.
+ */
+ int getApiLevelRequirement() {
+ return mApiLevelRequirement;
+ }
+
/* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#setDocumentLocator(org.xml.sax.Locator)
*/
@@ -171,7 +182,7 @@
// if we're at a valid level
if (mValidLevel == mCurrentLevel) {
- String processName;
+ String value;
switch (mValidLevel) {
case LEVEL_MANIFEST:
if (NODE_MANIFEST.equals(localName)) {
@@ -183,19 +194,28 @@
break;
case LEVEL_APPLICATION:
if (NODE_APPLICATION.equals(localName)) {
- processName = getAttributeValue(attributes, ATTRIBUTE_PROCESS,
+ value = getAttributeValue(attributes, ATTRIBUTE_PROCESS,
true /* hasNamespace */);
- if (processName != null) {
- addProcessName(processName);
+ if (value != null) {
+ addProcessName(value);
}
- String debuggable = getAttributeValue(attributes,
- ATTRIBUTE_DEBUGGABLE, true /* hasNamespace*/);
- if (debuggable != null) {
- mDebuggable = Boolean.parseBoolean(debuggable);
+ value = getAttributeValue(attributes, ATTRIBUTE_DEBUGGABLE,
+ true /* hasNamespace*/);
+ if (value != null) {
+ mDebuggable = Boolean.parseBoolean(value);
}
mValidLevel++;
+ } else if (NODE_USES_SDK.equals(localName)) {
+ value = getAttributeValue(attributes, ATTRIBUTE_MIN_SDK_VERSION,
+ true /* hasNamespace */);
+
+ try {
+ mApiLevelRequirement = Integer.parseInt(value);
+ } catch (NumberFormatException e) {
+ handleError(e, -1 /* lineNumber */);
+ }
}
break;
case LEVEL_ACTIVITY:
@@ -301,7 +321,7 @@
@Override
public void error(SAXParseException e) throws SAXException {
if (mMarkErrors) {
- super.error(e);
+ handleError(e, e.getLineNumber());
}
}
@@ -311,7 +331,7 @@
@Override
public void fatalError(SAXParseException e) throws SAXException {
if (mMarkErrors) {
- super.fatalError(e);
+ handleError(e, e.getLineNumber());
}
}
@@ -457,6 +477,7 @@
private final String mLauncherActivity;
private final String[] mProcesses;
private final Boolean mDebuggable;
+ private final int mApiLevelRequirement;
static {
sParserFactory = SAXParserFactory.newInstance();
@@ -491,7 +512,8 @@
return new AndroidManifestParser(manifestHandler.getPackage(),
manifestHandler.getActivities(), manifestHandler.getLauncherActivity(),
- manifestHandler.getProcesses(), manifestHandler.getDebuggable());
+ manifestHandler.getProcesses(), manifestHandler.getDebuggable(),
+ manifestHandler.getApiLevelRequirement());
} catch (ParserConfigurationException e) {
} catch (SAXException e) {
} catch (IOException e) {
@@ -530,7 +552,8 @@
// get the result from the handler
return new AndroidManifestParser(manifestHandler.getPackage(),
manifestHandler.getActivities(), manifestHandler.getLauncherActivity(),
- manifestHandler.getProcesses(), manifestHandler.getDebuggable());
+ manifestHandler.getProcesses(), manifestHandler.getDebuggable(),
+ manifestHandler.getApiLevelRequirement());
}
} catch (ParserConfigurationException e) {
} catch (SAXException e) {
@@ -610,6 +633,14 @@
}
/**
+ * Returns the <code>minSdkVersion</code> attribute, or 0 if it's not set.
+ */
+ public int getApiLevelRequirement() {
+ return mApiLevelRequirement;
+ }
+
+
+ /**
* Private constructor to enforce using
* {@link #parse(IJavaProject, XmlErrorListener, boolean, boolean)},
* {@link #parse(IJavaProject, IFile, XmlErrorListener, boolean, boolean)},
@@ -619,14 +650,17 @@
* @param activities the list of activities parsed from the manifest.
* @param launcherActivity the launcher activity parser from the manifest.
* @param processes the list of custom processes declared in the manifest.
- * @param debuggable the debuggable attribute.
+ * @param debuggable the debuggable attribute, or null if not set.
+ * @param apiLevelRequirement the minSdkVersion attribute value or 0 if not set.
*/
private AndroidManifestParser(String javaPackage, String[] activities,
- String launcherActivity, String[] processes, Boolean debuggable) {
+ String launcherActivity, String[] processes, Boolean debuggable,
+ int apiLevelRequirement) {
mJavaPackage = javaPackage;
mActivities = activities;
mLauncherActivity = launcherActivity;
mProcesses = processes;
mDebuggable = debuggable;
+ mApiLevelRequirement = apiLevelRequirement;
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidXPathFactory.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidXPathFactory.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidXPathFactory.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidXPathFactory.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/BaseProjectHelper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/BaseProjectHelper.java
similarity index 98%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/BaseProjectHelper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/BaseProjectHelper.java
index 57ca496..c69e875 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/BaseProjectHelper.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/BaseProjectHelper.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.common.project;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.CommonPlugin;
import com.android.ide.eclipse.common.project.XmlErrorHandler.XmlErrorListener;
import org.eclipse.core.resources.IFile;
@@ -108,7 +108,7 @@
return marker;
} catch (CoreException e) {
- CommonPlugin.log(e, "Failed to add marker '%1$s' to '%2$s'",
+ AdtPlugin.log(e, "Failed to add marker '%1$s' to '%2$s'",
markerId, file.getFullPath());
}
@@ -117,10 +117,9 @@
/**
* Adds a marker to a resource.
- * @param file the file to be marked
+ * @param resource the file to be marked
* @param markerId The id of the marker to add.
* @param message the message associated with the mark
- * @param lineNumber the line number where to put the mark
* @param severity the severity of the marker.
* @return the IMarker that was added or null if it failed to add one.
*/
@@ -138,7 +137,7 @@
return marker;
} catch (CoreException e) {
- CommonPlugin.log(e, "Failed to add marker '%1$s' to '%2$s'",
+ AdtPlugin.log(e, "Failed to add marker '%1$s' to '%2$s'",
markerId, resource.getFullPath());
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/ExportHelper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/ExportHelper.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/ExportHelper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/ExportHelper.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/ProjectChooserHelper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/ProjectChooserHelper.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/ProjectChooserHelper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/ProjectChooserHelper.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java
similarity index 77%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java
index 3492cb4..26fbf42 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java
@@ -65,11 +65,7 @@
*/
@Override
public void error(SAXParseException exception) throws SAXException {
- if (mErrorListener != null) {
- mErrorListener.errorFound();
- }
- BaseProjectHelper.addMarker(mFile, AndroidConstants.MARKER_XML, exception.getMessage(),
- exception.getLineNumber(), IMarker.SEVERITY_ERROR);
+ handleError(exception, exception.getLineNumber());
}
/**
@@ -77,13 +73,8 @@
* @param exception the parsing exception
*/
@Override
- public void fatalError(SAXParseException exception)
- throws SAXException {
- if (mErrorListener != null) {
- mErrorListener.errorFound();
- }
- BaseProjectHelper.addMarker(mFile, AndroidConstants.MARKER_XML, exception.getMessage(),
- exception.getLineNumber(), IMarker.SEVERITY_ERROR);
+ public void fatalError(SAXParseException exception) throws SAXException {
+ handleError(exception, exception.getLineNumber());
}
/**
@@ -99,4 +90,23 @@
protected final IFile getFile() {
return mFile;
}
+
+ /**
+ * Handles a parsing error and an optional line number.
+ * @param exception
+ * @param lineNumber
+ */
+ protected void handleError(Exception exception, int lineNumber) {
+ if (mErrorListener != null) {
+ mErrorListener.errorFound();
+ }
+
+ if (lineNumber != -1) {
+ BaseProjectHelper.addMarker(mFile, AndroidConstants.MARKER_XML, exception.getMessage(),
+ lineNumber, IMarker.SEVERITY_ERROR);
+ } else {
+ BaseProjectHelper.addMarker(mFile, AndroidConstants.MARKER_XML, exception.getMessage(),
+ IMarker.SEVERITY_ERROR);
+ }
+ }
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/AttrsXmlParser.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/AttrsXmlParser.java
similarity index 95%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/AttrsXmlParser.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/AttrsXmlParser.java
index 43260c0..3176c8e 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/AttrsXmlParser.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/AttrsXmlParser.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.common.resources;
-import com.android.ide.eclipse.common.CommonPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.resources.DeclareStyleableInfo.AttributeInfo;
import com.android.ide.eclipse.common.resources.DeclareStyleableInfo.AttributeInfo.Format;
import com.android.ide.eclipse.common.resources.ViewClassInfo.LayoutParamsInfo;
@@ -106,7 +106,7 @@
Document doc = getDocument();
if (doc == null) {
- CommonPlugin.log(IStatus.WARNING, "Failed to find %1$s", //$NON-NLS-1$
+ AdtPlugin.log(IStatus.WARNING, "Failed to find %1$s", //$NON-NLS-1$
mOsAttrsXmlPath);
return this;
}
@@ -119,7 +119,7 @@
}
if (res == null) {
- CommonPlugin.log(IStatus.WARNING, "Failed to find a <resources> node in %1$s", //$NON-NLS-1$
+ AdtPlugin.log(IStatus.WARNING, "Failed to find a <resources> node in %1$s", //$NON-NLS-1$
mOsAttrsXmlPath);
return this;
}
@@ -189,13 +189,13 @@
DocumentBuilder builder = factory.newDocumentBuilder();
mDocument = builder.parse(new File(mOsAttrsXmlPath));
} catch (ParserConfigurationException e) {
- CommonPlugin.log(e, "Failed to create XML document builder for %1$s", //$NON-NLS-1$
+ AdtPlugin.log(e, "Failed to create XML document builder for %1$s", //$NON-NLS-1$
mOsAttrsXmlPath);
} catch (SAXException e) {
- CommonPlugin.log(e, "Failed to parse XML document %1$s", //$NON-NLS-1$
+ AdtPlugin.log(e, "Failed to parse XML document %1$s", //$NON-NLS-1$
mOsAttrsXmlPath);
} catch (IOException e) {
- CommonPlugin.log(e, "Failed to read XML document %1$s", //$NON-NLS-1$
+ AdtPlugin.log(e, "Failed to read XML document %1$s", //$NON-NLS-1$
mOsAttrsXmlPath);
}
}
@@ -340,7 +340,7 @@
formats.add(format);
}
} catch (IllegalArgumentException e) {
- CommonPlugin.log(e, "Unknown format name '%s' in <attr name=\"%s\">, file '%s'.", //$NON-NLS-1$
+ AdtPlugin.log(e, "Unknown format name '%s' in <attr name=\"%s\">, file '%s'.", //$NON-NLS-1$
f, name, getOsAttrsXmlPath());
}
}
@@ -389,7 +389,7 @@
if (child.getNodeType() == Node.ELEMENT_NODE && child.getNodeName().equals(filter)) {
Node nameNode = child.getAttributes().getNamedItem("name"); //$NON-NLS-1$
if (nameNode == null) {
- CommonPlugin.log(IStatus.WARNING,
+ AdtPlugin.log(IStatus.WARNING,
"Missing name attribute in <attr name=\"%s\"><%s></attr>", //$NON-NLS-1$
attrName, filter);
} else {
@@ -401,7 +401,7 @@
Node valueNode = child.getAttributes().getNamedItem("value"); //$NON-NLS-1$
if (valueNode == null) {
- CommonPlugin.log(IStatus.WARNING,
+ AdtPlugin.log(IStatus.WARNING,
"Missing value attribute in <attr name=\"%s\"><%s name=\"%s\"></attr>", //$NON-NLS-1$
attrName, filter, name);
} else {
@@ -419,7 +419,7 @@
map.put(name, Integer.valueOf(i));
} catch(NumberFormatException e) {
- CommonPlugin.log(e,
+ AdtPlugin.log(e,
"Value in <attr name=\"%s\"><%s name=\"%s\" value=\"%s\"></attr> is not a valid decimal or hexadecimal", //$NON-NLS-1$
attrName, filter, name, value);
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/DeclareStyleableInfo.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/DeclareStyleableInfo.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/DeclareStyleableInfo.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/DeclareStyleableInfo.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/IIdResourceItem.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/IIdResourceItem.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/IIdResourceItem.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/IIdResourceItem.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/IPathChangedListener.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/IPathChangedListener.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/IPathChangedListener.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/IPathChangedListener.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/IResourceRepository.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/IResourceRepository.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/IResourceRepository.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/IResourceRepository.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ResourceItem.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ResourceItem.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ResourceItem.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ResourceItem.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ResourceType.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ResourceType.java
similarity index 83%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ResourceType.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ResourceType.java
index 3d64e5d..60c471e 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ResourceType.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ResourceType.java
@@ -21,7 +21,7 @@
*/
public enum ResourceType {
ANIM("anim", "Animation"), //$NON-NLS-1$
- ARRAY("array", "Array"), //$NON-NLS-1$
+ ARRAY("array", "Array", "string-array", "integer-array"), //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-4$
ATTR("attr", "Attr"), //$NON-NLS-1$
COLOR("color", "Color"), //$NON-NLS-1$
DIMEN("dimen", "Dimension"), //$NON-NLS-1$
@@ -35,12 +35,14 @@
STYLEABLE("styleable", "Styleable"), //$NON-NLS-1$
XML("xml", "XML"); //$NON-NLS-1$
- private String mName;
- private String mDisplayName;
+ private final String mName;
+ private final String mDisplayName;
+ private final String[] mAlternateXmlNames;
- ResourceType(String name, String displayName) {
+ ResourceType(String name, String displayName, String... alternateXmlNames) {
mName = name;
mDisplayName = displayName;
+ mAlternateXmlNames = alternateXmlNames;
}
/**
@@ -66,6 +68,13 @@
for (ResourceType rType : values()) {
if (rType.mName.equals(name)) {
return rType;
+ } else if (rType.mAlternateXmlNames != null) {
+ // if there are alternate Xml Names, we test those too
+ for (String alternate : rType.mAlternateXmlNames) {
+ if (alternate.equals(name)) {
+ return rType;
+ }
+ }
}
}
return null;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ViewClassInfo.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ViewClassInfo.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ViewClassInfo.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ViewClassInfo.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidContentAssist.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidContentAssist.java
similarity index 94%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidContentAssist.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidContentAssist.java
index 1dd0c27..d1b4547 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidContentAssist.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidContentAssist.java
@@ -16,11 +16,12 @@
package com.android.ide.eclipse.editors;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.TextValueDescriptor;
@@ -80,15 +81,20 @@
protected final static String ROOT_ELEMENT = "";
/** Descriptor of the root of the XML hierarchy. This a "fake" ElementDescriptor which
- * is used to list all the possible roots given by actual implementations. */
+ * is used to list all the possible roots given by actual implementations.
+ * DO NOT USE DIRECTLY. Call {@link #getRootDescriptor()} instead. */
private ElementDescriptor mRootDescriptor;
+ private final int mDescriptorId;
+
+ private AndroidEditor mEditor;
+
/**
* Constructor for AndroidContentAssist
* @param rootElementDescriptors The valid root elements of the XML hierarchy
*/
- public AndroidContentAssist(ElementDescriptor[] rootElementDescriptors) {
- mRootDescriptor = new ElementDescriptor("", rootElementDescriptors);
+ public AndroidContentAssist(int descriptorId) {
+ mDescriptorId = descriptorId;
}
/**
@@ -104,8 +110,11 @@
*/
public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
- AndroidEditor editor = getAndroidEditor(viewer);
- UiElementNode rootUiNode = editor.getUiRootNode();
+ if (mEditor == null) {
+ mEditor = getAndroidEditor(viewer);
+ }
+
+ UiElementNode rootUiNode = mEditor.getUiRootNode();
Object[] choices = null; /* An array of ElementDescriptor, or AttributeDescriptor
or String or null */
@@ -245,7 +254,7 @@
if (current_node.getParentNode().getNodeType() == Node.ELEMENT_NODE) {
grandparent = getDescriptor(current_node.getParentNode().getNodeName());
} else if (current_node.getParentNode().getNodeType() == Node.DOCUMENT_NODE) {
- grandparent = mRootDescriptor;
+ grandparent = getRootDescriptor();
}
if (grandparent != null) {
for (ElementDescriptor e : grandparent.getChildren()) {
@@ -339,8 +348,11 @@
greatGrandParentName = greatGrandParent.getLocalName();
}
}
- choices = FrameworkResourceManager.getInstance().getValues(
- parent, attrInfo.name, greatGrandParentName);
+
+ AndroidTargetData data = mEditor.getTargetData();
+ if (data != null) {
+ choices = data.getAttributeValues(parent, attrInfo.name, greatGrandParentName);
+ }
}
} else {
// Editing an attribute's name... Get attributes valid for the parent node.
@@ -378,7 +390,7 @@
} else if (parent_node.getNodeType() == Node.DOCUMENT_NODE) {
// We're editing a text node at the first level (i.e. root node).
// Limit content assist to the only valid root elements.
- choices = mRootDescriptor.getChildren();
+ choices = getRootDescriptor().getChildren();
}
return choices;
}
@@ -509,7 +521,7 @@
* is returned.
*/
private ElementDescriptor getDescriptor(String nodeName) {
- return mRootDescriptor.findChildrenDescriptor(nodeName, true /* recursive */);
+ return getRootDescriptor().findChildrenDescriptor(nodeName, true /* recursive */);
}
public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
@@ -539,8 +551,8 @@
public String getErrorMessage() {
return null;
- }
-
+ }
+
/**
* Heuristically extracts the prefix used for determining template relevance
* from the viewer's document. The default implementation returns the String from
@@ -710,6 +722,26 @@
}
/**
+ * Computes (if needed) and returns the root descriptor.
+ * @return
+ */
+ private ElementDescriptor getRootDescriptor() {
+ if (mRootDescriptor == null) {
+ AndroidTargetData data = mEditor.getTargetData();
+ if (data != null) {
+ IDescriptorProvider descriptorProvider = data.getDescriptorProvider(mDescriptorId);
+
+ if (descriptorProvider != null) {
+ mRootDescriptor = new ElementDescriptor("",
+ descriptorProvider.getRootElementDescriptors());
+ }
+ }
+ }
+
+ return mRootDescriptor;
+ }
+
+ /**
* Returns the active {@link AndroidEditor} matching this source viewer.
*/
private AndroidEditor getAndroidEditor(ITextViewer viewer) {
@@ -729,5 +761,7 @@
return null;
}
+
+
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidEditor.java
similarity index 74%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidEditor.java
index 74eca96..78e0401 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidEditor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidEditor.java
@@ -16,10 +16,14 @@
package com.android.ide.eclipse.editors;
-import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
@@ -29,15 +33,18 @@
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.editor.FormEditor;
@@ -71,7 +78,7 @@
* source editor. This can be a no-op if desired.
*/
public abstract class AndroidEditor extends FormEditor implements IResourceChangeListener {
-
+
/** Preference name for the current page of this file */
private static final String PREF_CURRENT_PAGE = "_current_page";
@@ -87,9 +94,11 @@
/** Page index of the text editor (always the last page) */
private int mTextPageIndex;
/** The text editor */
- private StructuredTextEditor mEditor;
+ private StructuredTextEditor mTextEditor;
/** Listener for the XML model from the StructuredEditor */
private XmlModelStateListener mXmlModelStateListener;
+ /** Listener to update the root node if the resource framework changes */
+ private Runnable mResourceRefreshListener;
/**
* Creates a form editor.
@@ -97,6 +106,16 @@
public AndroidEditor() {
super();
ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
+
+ mResourceRefreshListener = new Runnable() {
+ public void run() {
+ commitPages(false /* onSave */);
+
+ // recreate the ui root node always
+ initUiRootNode(true /*force*/);
+ }
+ };
+ AdtPlugin.getDefault().addResourceChangedListener(mResourceRefreshListener);
}
// ---- Abstract Methods ----
@@ -113,6 +132,12 @@
* Derived classes must implement this to add their own specific tabs.
*/
abstract protected void createFormPages();
+
+ /**
+ * Creates the initial UI Root Node, including the known mandatory elements.
+ * @param force if true, a new UiManifestNode is recreated even if it already exists.
+ */
+ abstract protected void initUiRootNode(boolean force);
/**
* Subclasses should override this method to process the new XML Model, which XML
@@ -143,6 +168,26 @@
protected void createAndroidPages() {
createFormPages();
createTextEditor();
+
+ createUndoRedoActions();
+ }
+
+ /**
+ * Creates undo redo actions for the editor site (so that it works for any page of this
+ * multi-page editor) by re-using the actions defined by the {@link StructuredTextEditor}
+ * (aka the XML text editor.)
+ */
+ private void createUndoRedoActions() {
+ IActionBars bars = getEditorSite().getActionBars();
+ if (bars != null) {
+ IAction action = mTextEditor.getAction(ActionFactory.UNDO.getId());
+ bars.setGlobalActionHandler(ActionFactory.UNDO.getId(), action);
+
+ action = mTextEditor.getAction(ActionFactory.REDO.getId());
+ bars.setGlobalActionHandler(ActionFactory.REDO.getId(), action);
+
+ bars.updateActionBars();
+ }
}
/**
@@ -155,7 +200,7 @@
if (getEditorInput() instanceof IFileEditorInput) {
IFile file = ((IFileEditorInput) getEditorInput()).getFile();
- QualifiedName qname = new QualifiedName(AndroidConstants.EDITORS_PLUGIN_ID,
+ QualifiedName qname = new QualifiedName(AdtPlugin.PLUGIN_ID,
getClass().getSimpleName() + PREF_CURRENT_PAGE);
String pageId;
try {
@@ -177,7 +222,7 @@
// AssertionError from setActivePage when the index is out of bounds.
// Generally speaking we just want to ignore any exception and fall back on the
// first page rather than crash the editor load. Logging the error is enough.
- EditorsPlugin.log(e, "Selecting page '%s' in AndroidEditor failed", defaultPageId);
+ AdtPlugin.log(e, "Selecting page '%s' in AndroidEditor failed", defaultPageId);
}
}
}
@@ -224,7 +269,7 @@
if (getEditorInput() instanceof IFileEditorInput) {
IFile file = ((IFileEditorInput) getEditorInput()).getFile();
- QualifiedName qname = new QualifiedName(AndroidConstants.EDITORS_PLUGIN_ID,
+ QualifiedName qname = new QualifiedName(AdtPlugin.PLUGIN_ID,
getClass().getSimpleName() + PREF_CURRENT_PAGE);
try {
file.setPersistentProperty(qname, Integer.toString(newPageIndex));
@@ -248,10 +293,10 @@
IWorkbenchPage[] pages = getSite().getWorkbenchWindow()
.getPages();
for (int i = 0; i < pages.length; i++) {
- if (((FileEditorInput)mEditor.getEditorInput())
+ if (((FileEditorInput)mTextEditor.getEditorInput())
.getFile().getProject().equals(
event.getResource())) {
- IEditorPart editorPart = pages[i].findEditor(mEditor
+ IEditorPart editorPart = pages[i].findEditor(mTextEditor
.getEditorInput());
pages[i].closeEditor(editorPart, true);
}
@@ -294,6 +339,12 @@
}
}
ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
+
+ if (mResourceRefreshListener != null) {
+ AdtPlugin.getDefault().removeResourceChangedListener(mResourceRefreshListener);
+ mResourceRefreshListener = null;
+ }
+
super.dispose();
}
@@ -447,13 +498,13 @@
*/
private void createTextEditor() {
try {
- mEditor = new StructuredTextEditor();
- int index = addPage(mEditor, getEditorInput());
+ mTextEditor = new StructuredTextEditor();
+ int index = addPage(mTextEditor, getEditorInput());
mTextPageIndex = index;
- setPageText(index, mEditor.getTitle());
+ setPageText(index, mTextEditor.getTitle());
- if (!(mEditor.getTextViewer().getDocument() instanceof IStructuredDocument)) {
- Status status = new Status(IStatus.ERROR, AndroidConstants.EDITORS_PLUGIN_ID,
+ if (!(mTextEditor.getTextViewer().getDocument() instanceof IStructuredDocument)) {
+ Status status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
"Error opening the Android XML editor. Is the document an XML file?");
throw new RuntimeException("Android XML Editor Error", new CoreException(status));
}
@@ -464,6 +515,8 @@
mXmlModelStateListener = new XmlModelStateListener();
xml_model.addModelStateListener(mXmlModelStateListener);
mXmlModelStateListener.modelChanged(xml_model);
+ } catch (Exception e) {
+ AdtPlugin.log(e, "Error while loading editor"); //$NON-NLS-1$
} finally {
xml_model.releaseFromRead();
}
@@ -478,11 +531,11 @@
* Returns the ISourceViewer associated with the Structured Text editor.
*/
public final ISourceViewer getStructuredSourceViewer() {
- if (mEditor != null) {
+ if (mTextEditor != null) {
// We can't access mEditor.getSourceViewer() because it is protected,
// however getTextViewer simply returns the SourceViewer casted, so we
// can use it instead.
- return mEditor.getTextViewer();
+ return mTextEditor.getTextViewer();
}
return null;
}
@@ -492,8 +545,8 @@
* Editor) or null if not available.
*/
public final IStructuredDocument getStructuredDocument() {
- if (mEditor != null && mEditor.getTextViewer() != null) {
- return (IStructuredDocument) mEditor.getTextViewer().getDocument();
+ if (mTextEditor != null && mTextEditor.getTextViewer() != null) {
+ return (IStructuredDocument) mTextEditor.getTextViewer().getDocument();
}
return null;
}
@@ -539,14 +592,17 @@
/**
* Helper class to perform edits on the XML model whilst making sure the
* model has been prepared to be changed.
+ * <p/>
+ * It first gets a model for edition using {@link #getModelForEdit()},
+ * then calls {@link IStructuredModel#aboutToChangeModel()},
+ * then performs the requested action
+ * and finally calls {@link IStructuredModel#changedModel()}
+ * and {@link IStructuredModel#releaseFromEdit()}.
+ * <p/>
+ * The method is synchronous. As soon as the {@link IStructuredModel#changedModel()} method
+ * is called, XML model listeners will be triggered.
*
- * It first gets a model for edition, then calls aboutToChangeModel, then performs the
- * requested action and finally calls changedModel and releaseFromEdit.
- *
- * The method is synchronous. As soon as the changedModel method is called, XML model
- * listeners will be triggered.
- *
- * @param edit_action Something that will change
+ * @param edit_action Something that will change the XML.
*/
public final void editXmlModel(Runnable edit_action) {
IStructuredModel model = getModelForEdit();
@@ -561,11 +617,81 @@
}
/**
+ * Starts an "undo recording" session. This is managed by the underlying undo manager
+ * associated to the structured XML model.
+ * <p/>
+ * There <em>must</em> be a corresponding call to {@link #endUndoRecording()}.
+ * <p/>
+ * beginUndoRecording/endUndoRecording calls can be nested (inner calls are ignored, only one
+ * undo operation is recorded.)
+ *
+ * @param label The label for the undo operation. Can be null but we should really try to put
+ * something meaningful if possible.
+ * @return True if the undo recording actually started, false if any kind of error occured.
+ * {@link #endUndoRecording()} should only be called if True is returned.
+ */
+ private final boolean beginUndoRecording(String label) {
+ IStructuredDocument document = getStructuredDocument();
+ if (document != null) {
+ IModelManager mm = StructuredModelManager.getModelManager();
+ if (mm != null) {
+ IStructuredModel model = mm.getModelForEdit(document);
+ if (model != null) {
+ model.beginRecording(this, label);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Ends an "undo recording" session.
+ * <p/>
+ * This is the counterpart call to {@link #beginUndoRecording(String)} and should only be
+ * used if the initial call returned true.
+ */
+ private final void endUndoRecording() {
+ IStructuredDocument document = getStructuredDocument();
+ if (document != null) {
+ IModelManager mm = StructuredModelManager.getModelManager();
+ if (mm != null) {
+ IStructuredModel model = mm.getModelForEdit(document);
+ if (model != null) {
+ model.endRecording(this);
+ }
+ }
+ }
+ }
+
+ /**
+ * Creates an "undo recording" session by calling the undoableAction runnable
+ * using {@link #beginUndoRecording(String)} and {@link #endUndoRecording()}.
+ * <p>
+ * You can nest several calls to {@link #wrapUndoRecording(String, Runnable)}, only one
+ * recording session will be created.
+ *
+ * @param label The label for the undo operation. Can be null. Ideally we should really try
+ * to put something meaningful if possible.
+ */
+ public void wrapUndoRecording(String label, Runnable undoableAction) {
+ boolean recording = false;
+ try {
+ recording = beginUndoRecording(label);
+ undoableAction.run();
+ } finally {
+ if (recording) {
+ endUndoRecording();
+ }
+ }
+ }
+
+ /**
* Returns the XML {@link Document} or null if we can't get it
*/
protected final Document getXmlDocument(IStructuredModel model) {
if (model == null) {
- EditorsPlugin.log(IStatus.WARNING, "Android Editor: No XML model for root node."); //$NON-NLS-1$
+ AdtPlugin.log(IStatus.WARNING, "Android Editor: No XML model for root node."); //$NON-NLS-1$
return null;
}
@@ -577,6 +703,45 @@
}
/**
+ * Returns the {@link IProject} for the edited file.
+ */
+ public IProject getProject() {
+ if (mTextEditor != null) {
+ IEditorInput input = mTextEditor.getEditorInput();
+ if (input instanceof FileEditorInput) {
+ FileEditorInput fileInput = (FileEditorInput)input;
+ IFile inputFile = fileInput.getFile();
+
+ if (inputFile != null) {
+ return inputFile.getProject();
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the {@link PlatformData} for the edited file.
+ */
+ public AndroidTargetData getTargetData() {
+ IProject project = getProject();
+ if (project != null) {
+ Sdk currentSdk = Sdk.getCurrent();
+ if (currentSdk != null) {
+ IAndroidTarget target = currentSdk.getTarget(project);
+
+ if (target != null) {
+ return currentSdk.getTargetData(target);
+ }
+ }
+ }
+
+ return null;
+ }
+
+
+ /**
* Listen to changes in the underlying XML model in the structured editor.
*/
private class XmlModelStateListener implements IModelStateListener {
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidSourceViewerConfig.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidSourceViewerConfig.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidSourceViewerConfig.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidSourceViewerConfig.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/FirstElementParser.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/FirstElementParser.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/FirstElementParser.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/FirstElementParser.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/IconFactory.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/IconFactory.java
similarity index 97%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/IconFactory.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/IconFactory.java
index 9e3b733..e3de3af 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/IconFactory.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/IconFactory.java
@@ -17,6 +17,7 @@
package com.android.ide.eclipse.editors;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
import org.eclipse.jface.resource.ImageDescriptor;
@@ -100,8 +101,6 @@
* one of SHAPE_DEFAULT, SHAPE_CIRCLE or SHAPE_RECT.
*/
public Image getIcon(String osName, int color, int shape) {
- EditorsPlugin plugin = EditorsPlugin.getDefault();
-
String key = Character.toString((char) shape) + Integer.toString(color) + osName;
Image icon = mIconMap.get(key);
if (icon == null && !mIconMap.containsKey(key)) {
@@ -143,13 +142,11 @@
* one of SHAPE_DEFAULT, SHAPE_CIRCLE or SHAPE_RECT.
*/
public ImageDescriptor getImageDescriptor(String osName, int color, int shape) {
- EditorsPlugin plugin = EditorsPlugin.getDefault();
-
String key = Character.toString((char) shape) + Integer.toString(color) + osName;
ImageDescriptor id = mImageDescMap.get(key);
if (id == null && !mImageDescMap.containsKey(key)) {
- id = plugin.imageDescriptorFromPlugin(
- AndroidConstants.EDITORS_PLUGIN_ID,
+ id = AdtPlugin.imageDescriptorFromPlugin(
+ AdtPlugin.PLUGIN_ID,
String.format("/icons/%1$s.png", osName)); //$NON-NLS-1$
if (id == null) {
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptor.java
similarity index 82%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptor.java
index 48fa903..2c779b2 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptor.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.descriptors;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.IconFactory;
import com.android.ide.eclipse.editors.uimodel.UiAttributeNode;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
@@ -61,30 +61,6 @@
public final String getNamespaceUri() {
return mNsUri;
}
-
- /**
- * Returns the XML qualified name of the attribute (case sensitive, with namespace prefix
- * if present)
- *
- * @deprecated
- */
- private final String getXmlName() {
- return mXmlLocalName;
- }
-
- /**
- * Returns the namespace of the attribute.
- *
- * @deprecated
- */
- private final String getNamespace() {
- // For now we hard-code the prefix as being "android"
- if (mXmlLocalName.startsWith("android:")) { //$NON-NLs-1$
- return AndroidConstants.NS_RESOURCES;
- }
-
- return ""; //$NON-NLs-1$
- }
final void setParent(ElementDescriptor parent) {
mParent = parent;
@@ -107,7 +83,7 @@
IconFactory factory = IconFactory.getInstance();
Image icon;
icon = factory.getIcon(getXmlLocalName(), IconFactory.COLOR_RED, IconFactory.SHAPE_CIRCLE);
- return icon != null ? icon : EditorsPlugin.getAndroidLogo();
+ return icon != null ? icon : AdtPlugin.getAndroidLogo();
}
/**
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptorLabelProvider.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptorLabelProvider.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptorLabelProvider.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptorLabelProvider.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/BooleanAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/BooleanAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/BooleanAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/BooleanAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DescriptorsUtils.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/DescriptorsUtils.java
similarity index 85%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DescriptorsUtils.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/DescriptorsUtils.java
index f848d79..c84bf57 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DescriptorsUtils.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/DescriptorsUtils.java
@@ -20,6 +20,8 @@
import com.android.ide.eclipse.common.resources.ResourceType;
import com.android.ide.eclipse.common.resources.DeclareStyleableInfo.AttributeInfo;
import com.android.ide.eclipse.common.resources.DeclareStyleableInfo.AttributeInfo.Format;
+import com.android.ide.eclipse.editors.layout.LayoutConstants;
+import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
import org.eclipse.swt.graphics.Image;
@@ -29,6 +31,7 @@
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -39,6 +42,8 @@
*/
public final class DescriptorsUtils {
+ private static final String DEFAULT_WIDGET_PREFIX = "widget";
+
private static final int JAVADOC_BREAK_LENGTH = 60;
/**
@@ -458,7 +463,8 @@
Image icon = elementDescriptor.getIcon();
if (icon != null) {
- sb.append("<form><li style=\"image\" value=\"" + IMAGE_KEY + "\">"); //$NON-NLS-1$ //$NON-NLS-2$
+ sb.append("<form><li style=\"image\" value=\"" + //$NON-NLS-1$
+ IMAGE_KEY + "\">"); //$NON-NLS-1$
} else {
sb.append("<form><p>"); //$NON-NLS-1$
}
@@ -573,13 +579,13 @@
// Detects {@link <base>#<name> <text>} where all 3 are optional
Pattern p_link = Pattern.compile("\\{@link\\s+([^#\\}\\s]*)(?:#([^\\s\\}]*))?(?:\\s*([^\\}]*))?\\}(.*)"); //$NON-NLS-1$
// Detects <code>blah</code>
- Pattern p_code = Pattern.compile("<code>(.+?)</code>(.*)"); //$NON-NLS-1$
+ Pattern p_code = Pattern.compile("<code>(.+?)</code>(.*)"); //$NON-NLS-1$
// Detects @blah@, used in hard-coded tooltip descriptors
- Pattern p_elem = Pattern.compile("@([\\w -]+)@(.*)"); //$NON-NLS-1$
+ Pattern p_elem = Pattern.compile("@([\\w -]+)@(.*)"); //$NON-NLS-1$
// Detects a buffer that starts by @ < or { (one that was not matched above)
- Pattern p_open = Pattern.compile("([@<\\{])(.*)"); //$NON-NLS-1$
+ Pattern p_open = Pattern.compile("([@<\\{])(.*)"); //$NON-NLS-1$
// Detects everything till the next potential separator, i.e. @ < or {
- Pattern p_text = Pattern.compile("([^@<\\{]+)(.*)"); //$NON-NLS-1$
+ Pattern p_text = Pattern.compile("([^@<\\{]+)(.*)"); //$NON-NLS-1$
int currentLength = 0;
String text = null;
@@ -668,28 +674,55 @@
* <p/>
* This does not override attributes which are not empty.
*/
- public static void setDefaultLayoutAttributes(UiElementNode ui_node) {
- ui_node.setAttributeValue("layout_width", "wrap_content", false /* override */); //$NON-NLS-1$ $NON-NLS-2$
- ui_node.setAttributeValue("layout_height", "wrap_content", false /* override */); //$NON-NLS-1$ $NON-NLS-2$
+ public static void setDefaultLayoutAttributes(UiElementNode ui_node, boolean updateLayout) {
+ // if this ui_node is a layout and we're adding it to a document, use fill_parent for
+ // both W/H. Otherwise default to wrap_layout.
+ boolean fill = ui_node.getDescriptor().hasChildren() &&
+ ui_node.getUiParent() instanceof UiDocumentNode;
+ ui_node.setAttributeValue(LayoutConstants.ATTR_LAYOUT_WIDTH,
+ fill ? LayoutConstants.VALUE_FILL_PARENT : LayoutConstants.VALUE_WRAP_CONTENT,
+ false /* override */);
+ ui_node.setAttributeValue(LayoutConstants.ATTR_LAYOUT_HEIGHT,
+ fill ? LayoutConstants.VALUE_FILL_PARENT : LayoutConstants.VALUE_WRAP_CONTENT,
+ false /* override */);
String widget_id = getFreeWidgetId(ui_node.getUiRoot(),
- new Object[] {ui_node.getDescriptor().getXmlLocalName(), 1, null });
+ new Object[] { ui_node.getDescriptor().getXmlLocalName(), null, null, null });
if (widget_id != null) {
- ui_node.setAttributeValue("id", "@+id/" + widget_id, false /* override */); //$NON-NLS-1$ $NON-NLS-2$
+ ui_node.setAttributeValue(LayoutConstants.ATTR_ID, "@+id/" + widget_id, //$NON-NLS-1$
+ false /* override */);
}
+
+ ui_node.setAttributeValue(LayoutConstants.ATTR_TEXT, widget_id, false /*override*/);
- UiElementNode ui_parent = ui_node.getUiParent();
- if (ui_parent != null && ui_parent.getDescriptor().getXmlLocalName().equals("RelativeLayout")) { //$NON-NLS-1$
- UiElementNode ui_previous = ui_node.getUiPreviousSibling();
- if (ui_previous != null) {
- String id = ui_previous.getAttributeValue("id"); //$NON-NLS-1$
- if (id != null && id.length() > 0) {
- id = id.replace("@+", "@");
- ui_node.setAttributeValue("layout_below", id, false /* override */);
+ if (updateLayout) {
+ UiElementNode ui_parent = ui_node.getUiParent();
+ if (ui_parent != null &&
+ ui_parent.getDescriptor().getXmlLocalName().equals(
+ LayoutConstants.RELATIVE_LAYOUT)) {
+ UiElementNode ui_previous = ui_node.getUiPreviousSibling();
+ if (ui_previous != null) {
+ String id = ui_previous.getAttributeValue(LayoutConstants.ATTR_ID);
+ if (id != null && id.length() > 0) {
+ id = id.replace("@+", "@"); //$NON-NLS-1$ //$NON-NLS-2$
+ ui_node.setAttributeValue(LayoutConstants.ATTR_LAYOUT_BELOW, id,
+ false /* override */);
+ }
}
}
}
-
+ }
+
+ /**
+ * Given a UI root node, returns the first available id that matches the
+ * pattern "prefix%02d".
+ *
+ * @param uiNode The UI node that gives the prefix to match.
+ * @return A suitable generated id
+ */
+ public static String getFreeWidgetId(UiElementNode uiNode) {
+ return getFreeWidgetId(uiNode.getUiRoot(),
+ new Object[] { uiNode.getDescriptor().getXmlLocalName(), null, null, null });
}
/**
@@ -698,19 +731,34 @@
*
* For recursion purposes, a "context" is given. Since Java doesn't have in-out parameters
* in methods and we're not going to do a dedicated type, we just use an object array which
- * must contain the following items:
- * - prefix(String): The prefix of the generated id, i.e. "widget"
- * - index(Integer): The minimum index of the generated id
- * - generated(String) The generated widget currently being searched. Must start with null.
+ * must contain one initial item and several are built on the fly just for internal storage:
+ * <ul>
+ * <li> prefix(String): The prefix of the generated id, i.e. "widget". Cannot be null.
+ * <li> index(Integer): The minimum index of the generated id. Must start with null.
+ * <li> generated(String): The generated widget currently being searched. Must start with null.
+ * <li> map(Set<String>): A set of the ids collected so far when walking through the widget
+ * hierarchy. Must start with null.
+ * </ul>
*
- * @param uiRoot The Ui root node where to start searching recusrively.
- * @param params An in-out context of parameters used during recursion, as explaine above.
+ * @param uiRoot The Ui root node where to start searching recursively. For the initial call
+ * you want to pass the document root.
+ * @param params An in-out context of parameters used during recursion, as explained above.
* @return A suitable generated id
*/
- private static String getFreeWidgetId(UiElementNode uiRoot, Object[] params) {
+ @SuppressWarnings("unchecked")
+ private static String getFreeWidgetId(UiElementNode uiRoot,
+ Object[] params) {
+
+ Set<String> map = (Set<String>)params[3];
+ if (map == null) {
+ params[3] = map = new HashSet<String>();
+ }
+
+ int num = params[1] == null ? 0 : ((Integer)params[1]).intValue();
+
String generated = (String) params[2];
+ String prefix = (String) params[0];
if (generated == null) {
- String prefix = (String) params[0];
int pos = prefix.indexOf('.');
if (pos >= 0) {
prefix = prefix.substring(pos + 1);
@@ -719,32 +767,42 @@
if (pos >= 0) {
prefix = prefix.substring(pos + 1);
}
- prefix = prefix.replaceAll("[^a-zA-Z]", ""); //$NON-NLS-1$ $NON-NLS-2$
+ prefix = prefix.replaceAll("[^a-zA-Z]", ""); //$NON-NLS-1$ $NON-NLS-2$
if (prefix.length() == 0) {
- prefix = "widget";
+ prefix = DEFAULT_WIDGET_PREFIX;
}
- generated = String.format("%1$s%2$02d", prefix, ((Integer)params[1]).intValue());
+
+ do {
+ num++;
+ generated = String.format("%1$s%2$02d", prefix, num); //$NON-NLS-1$
+ } while (map.contains(generated));
+
params[0] = prefix;
+ params[1] = num;
params[2] = generated;
}
- String id = uiRoot.getAttributeValue("id"); //$NON-NLS-1$
+ String id = uiRoot.getAttributeValue(LayoutConstants.ATTR_ID);
if (id != null) {
- id = id.replace("@+id/", ""); //$NON-NLS-1$ $NON-NLS-2$
- id = id.replace("@id/", ""); //$NON-NLS-1$ $NON-NLS-2$
- if (id.equals(generated)) {
- // switch to next value
- int num = ((Integer)params[1]).intValue() + 1;
- generated = String.format("%1$s%2$02d", params[0], num);
+ id = id.replace("@+id/", ""); //$NON-NLS-1$ $NON-NLS-2$
+ id = id.replace("@id/", ""); //$NON-NLS-1$ $NON-NLS-2$
+ if (map.add(id) && map.contains(generated)) {
+
+ do {
+ num++;
+ generated = String.format("%1$s%2$02d", prefix, num); //$NON-NLS-1$
+ } while (map.contains(generated));
+
params[1] = num;
params[2] = generated;
}
}
-
+
for (UiElementNode uiChild : uiRoot.getUiChildren()) {
getFreeWidgetId(uiChild, params);
}
+ // Note: return params[2] (not "generated") since it could have changed during recursion.
return (String) params[2];
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DocumentDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/DocumentDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DocumentDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/DocumentDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java
similarity index 98%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java
index 12ebc38..7d7b1c9 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.descriptors;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.IconFactory;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
@@ -173,7 +173,7 @@
int color = hasChildren() ? IconFactory.COLOR_BLUE : IconFactory.COLOR_GREEN;
int shape = hasChildren() ? IconFactory.SHAPE_RECT : IconFactory.SHAPE_CIRCLE;
Image icon = factory.getIcon(mXmlName, color, shape);
- return icon != null ? icon : EditorsPlugin.getAndroidLogo();
+ return icon != null ? icon : AdtPlugin.getAndroidLogo();
}
/**
@@ -190,7 +190,7 @@
int color = hasChildren() ? IconFactory.COLOR_BLUE : IconFactory.COLOR_GREEN;
int shape = hasChildren() ? IconFactory.SHAPE_RECT : IconFactory.SHAPE_CIRCLE;
ImageDescriptor id = factory.getImageDescriptor(mXmlName, color, shape);
- return id != null ? id : EditorsPlugin.getAndroidLogoDesc();
+ return id != null ? id : AdtPlugin.getAndroidLogoDesc();
}
/* Returns the list of allowed attributes. */
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/EnumAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/EnumAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/EnumAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/EnumAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/FlagAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/FlagAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/FlagAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/FlagAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/IDescriptorProvider.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/IDescriptorProvider.java
new file mode 100644
index 0000000..4c115e9
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/IDescriptorProvider.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.editors.descriptors;
+
+public interface IDescriptorProvider {
+
+ ElementDescriptor[] getRootElementDescriptors();
+
+ ElementDescriptor getDescriptor();
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ListAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ListAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ListAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ListAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ReferenceAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ReferenceAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ReferenceAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ReferenceAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/SeparatorAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/SeparatorAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/SeparatorAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/SeparatorAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/TextAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/TextAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/TextAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/TextAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/TextValueDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/TextValueDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/TextValueDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/TextValueDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/XmlnsAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/XmlnsAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/XmlnsAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/XmlnsAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/BasePullParser.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/BasePullParser.java
new file mode 100644
index 0000000..c512625
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/BasePullParser.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.editors.layout;
+
+import com.android.layoutlib.api.IXmlPullParser;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+/**
+ * Base implementation of an {@link IXmlPullParser} for cases where the parser is not sitting
+ * on top of an actual XML file.
+ * <p/>It's designed to work on layout files, and will most likely not work on other resource
+ * files.
+ */
+public abstract class BasePullParser implements IXmlPullParser {
+
+ protected int mParsingState = START_DOCUMENT;
+
+ public BasePullParser() {
+ }
+
+ // --- new methods to override ---
+
+ public abstract void onNextFromStartDocument();
+ public abstract void onNextFromStartTag();
+ public abstract void onNextFromEndTag();
+
+ // --- basic implementation of IXmlPullParser ---
+
+ public void setFeature(String name, boolean state) throws XmlPullParserException {
+ if (FEATURE_PROCESS_NAMESPACES.equals(name) && state) {
+ return;
+ }
+ if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name) && state) {
+ return;
+ }
+ throw new XmlPullParserException("Unsupported feature: " + name);
+ }
+
+ public boolean getFeature(String name) {
+ if (FEATURE_PROCESS_NAMESPACES.equals(name)) {
+ return true;
+ }
+ if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) {
+ return true;
+ }
+ return false;
+ }
+
+ public void setProperty(String name, Object value) throws XmlPullParserException {
+ throw new XmlPullParserException("setProperty() not supported");
+ }
+
+ public Object getProperty(String name) {
+ return null;
+ }
+
+ public void setInput(Reader in) throws XmlPullParserException {
+ throw new XmlPullParserException("setInput() not supported");
+ }
+
+ public void setInput(InputStream inputStream, String inputEncoding)
+ throws XmlPullParserException {
+ throw new XmlPullParserException("setInput() not supported");
+ }
+
+ public void defineEntityReplacementText(String entityName, String replacementText)
+ throws XmlPullParserException {
+ throw new XmlPullParserException("defineEntityReplacementText() not supported");
+ }
+
+ public String getNamespacePrefix(int pos) throws XmlPullParserException {
+ throw new XmlPullParserException("getNamespacePrefix() not supported");
+ }
+
+ public String getInputEncoding() {
+ return null;
+ }
+
+ public String getNamespace(String prefix) {
+ throw new RuntimeException("getNamespace() not supported");
+ }
+
+ public int getNamespaceCount(int depth) throws XmlPullParserException {
+ throw new XmlPullParserException("getNamespaceCount() not supported");
+ }
+
+ public String getNamespaceUri(int pos) throws XmlPullParserException {
+ throw new XmlPullParserException("getNamespaceUri() not supported");
+ }
+
+ public int getColumnNumber() {
+ return -1;
+ }
+
+ public int getLineNumber() {
+ return -1;
+ }
+
+ public String getAttributeType(int arg0) {
+ return "CDATA";
+ }
+
+ public int getEventType() {
+ return mParsingState;
+ }
+
+ public String getText() {
+ return null;
+ }
+
+ public char[] getTextCharacters(int[] arg0) {
+ return null;
+ }
+
+ public boolean isAttributeDefault(int arg0) {
+ return false;
+ }
+
+ public boolean isWhitespace() {
+ return false;
+ }
+
+ public int next() throws XmlPullParserException {
+ switch (mParsingState) {
+ case END_DOCUMENT:
+ throw new XmlPullParserException("Nothing after the end");
+ case START_DOCUMENT:
+ onNextFromStartDocument();
+ break;
+ case START_TAG:
+ onNextFromStartTag();
+ break;
+ case END_TAG:
+ onNextFromEndTag();
+ break;
+ case TEXT:
+ // not used
+ break;
+ case CDSECT:
+ // not used
+ break;
+ case ENTITY_REF:
+ // not used
+ break;
+ case IGNORABLE_WHITESPACE:
+ // not used
+ break;
+ case PROCESSING_INSTRUCTION:
+ // not used
+ break;
+ case COMMENT:
+ // not used
+ break;
+ case DOCDECL:
+ // not used
+ break;
+ }
+
+ return mParsingState;
+ }
+
+ public int nextTag() throws XmlPullParserException, IOException {
+ int eventType = next();
+ if (eventType != START_TAG && eventType != END_TAG) {
+ throw new XmlPullParserException("expected start or end tag", this, null);
+ }
+ return eventType;
+ }
+
+ public String nextText() throws XmlPullParserException, IOException {
+ if (getEventType() != START_TAG) {
+ throw new XmlPullParserException("parser must be on START_TAG to read next text", this,
+ null);
+ }
+ int eventType = next();
+ if (eventType == TEXT) {
+ String result = getText();
+ eventType = next();
+ if (eventType != END_TAG) {
+ throw new XmlPullParserException(
+ "event TEXT it must be immediately followed by END_TAG", this, null);
+ }
+ return result;
+ } else if (eventType == END_TAG) {
+ return "";
+ } else {
+ throw new XmlPullParserException("parser must be on START_TAG or TEXT to read text",
+ this, null);
+ }
+ }
+
+ public int nextToken() throws XmlPullParserException, IOException {
+ return next();
+ }
+
+ public void require(int type, String namespace, String name) throws XmlPullParserException {
+ if (type != getEventType() || (namespace != null && !namespace.equals(getNamespace()))
+ || (name != null && !name.equals(getName())))
+ throw new XmlPullParserException("expected " + TYPES[type] + getPositionDescription());
+ }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java
similarity index 75%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java
index 278b921..77467cd 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java
@@ -16,12 +16,18 @@
package com.android.ide.eclipse.editors.layout;
-import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.adt.sdk.LoadStatus;
+import com.android.ide.eclipse.adt.sdk.Sdk;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData.LayoutBridge;
import com.android.ide.eclipse.common.resources.ResourceType;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.IconFactory;
-import com.android.ide.eclipse.editors.EditorsPlugin.LayoutBridge;
+import com.android.ide.eclipse.editors.layout.LayoutEditor.UiEditorActions;
import com.android.ide.eclipse.editors.layout.LayoutReloadMonitor.ILayoutReloadListener;
+import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor;
+import com.android.ide.eclipse.editors.layout.parts.ElementCreateCommand;
+import com.android.ide.eclipse.editors.layout.parts.UiElementEditPart;
import com.android.ide.eclipse.editors.layout.parts.UiElementsEditPartFactory;
import com.android.ide.eclipse.editors.resources.configurations.CountryCodeQualifier;
import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration;
@@ -44,6 +50,8 @@
import com.android.ide.eclipse.editors.resources.manager.ResourceFile;
import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType;
import com.android.ide.eclipse.editors.resources.manager.ResourceManager;
+import com.android.ide.eclipse.editors.ui.tree.CopyCutAction;
+import com.android.ide.eclipse.editors.ui.tree.PasteAction;
import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
import com.android.ide.eclipse.editors.wizards.ConfigurationSelector.DensityVerifier;
@@ -55,6 +63,7 @@
import com.android.layoutlib.api.IResourceValue;
import com.android.layoutlib.api.IStyleResourceValue;
import com.android.layoutlib.api.ILayoutResult.ILayoutViewInfo;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
@@ -67,14 +76,22 @@
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.DefaultEditDomain;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.SelectionManager;
import org.eclipse.gef.dnd.TemplateTransferDragSourceListener;
import org.eclipse.gef.dnd.TemplateTransferDropTargetListener;
import org.eclipse.gef.editparts.ScalableFreeformRootEditPart;
import org.eclipse.gef.palette.PaletteRoot;
-import org.eclipse.gef.ui.parts.GraphicalEditor;
+import org.eclipse.gef.requests.CreationFactory;
+import org.eclipse.gef.ui.parts.GraphicalEditorWithPalette;
import org.eclipse.gef.ui.parts.SelectionSynchronizer;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.SWT;
@@ -85,6 +102,8 @@
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
@@ -98,6 +117,9 @@
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.FileEditorInput;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+import java.awt.image.Raster;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -105,6 +127,7 @@
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -112,20 +135,25 @@
/**
* Graphical layout editor, based on GEF.
+ * <p/>
+ * To understand GEF: http://www.ibm.com/developerworks/opensource/library/os-gef/
+ * <p/>
+ * To understand Drag'n'drop: http://www.eclipse.org/articles/Article-Workbench-DND/drag_drop.html
*/
-public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
+public class GraphicalLayoutEditor extends GraphicalEditorWithPalette
implements ILayoutReloadListener {
private final static String THEME_SEPARATOR = "----------"; //$NON-NLS-1$
/** Reference to the layout editor */
private final LayoutEditor mLayoutEditor;
-
+
/** reference to the file being edited. */
private IFile mEditedFile;
private Clipboard mClipboard;
private Composite mParent;
+ private PaletteRoot mPaletteRoot;
private Text mCountry;
private Text mNetwork;
@@ -141,7 +169,7 @@
private Text mSize2;
private Combo mThemeCombo;
private Button mCreateButton;
-
+
private Label mCountryIcon;
private Label mNetworkIcon;
private Label mLanguageIcon;
@@ -153,18 +181,18 @@
private Label mTextInputIcon;
private Label mNavigationIcon;
private Label mSizeIcon;
-
+
private Label mCurrentLayoutLabel;
private Image mWarningImage;
private Image mMatchImage;
private Image mErrorImage;
-
+
/** The {@link FolderConfiguration} representing the state of the UI controls */
private FolderConfiguration mCurrentConfig = new FolderConfiguration();
/** The {@link FolderConfiguration} being edited. */
private FolderConfiguration mEditedConfig;
-
+
private Map<String, Map<String, IResourceValue>> mConfiguredFrameworkRes;
private Map<String, Map<String, IResourceValue>> mConfiguredProjectRes;
private ProjectCallback mProjectCallback;
@@ -173,6 +201,7 @@
private boolean mNeedsRecompute = false;
private int mPlatformThemeCount = 0;
private boolean mDisableUpdates = false;
+ private boolean mActive = false;
private Runnable mFrameworkResourceChangeListener = new Runnable() {
public void run() {
@@ -180,6 +209,7 @@
mConfiguredFrameworkRes = null;
updateUIFromResources();
+
mThemeCombo.getParent().layout();
// updateUiFromFramework will reset language/region combo, so we must call
@@ -191,21 +221,21 @@
// make sure we remove the custom view loader, since its parent class loader is the
// bridge class loader.
mProjectCallback = null;
-
+
recomputeLayout();
}
};
-
+
private final Runnable mConditionalRecomputeRunnable = new Runnable() {
public void run() {
- if (mLayoutEditor.isGraphicalEditorActive()) {
+ if (mActive) {
recomputeLayout();
} else {
mNeedsRecompute = true;
}
}
};
-
+
private final Runnable mUiUpdateFromResourcesRunnable = new Runnable() {
public void run() {
updateUIFromResources();
@@ -217,19 +247,19 @@
mLayoutEditor = layoutEditor;
setEditDomain(new DefaultEditDomain(this));
setPartName("Layout");
-
+
IconFactory factory = IconFactory.getInstance();
mWarningImage = factory.getIcon("warning"); //$NON-NLS-1$
mMatchImage = factory.getIcon("match"); //$NON-NLS-1$
mErrorImage = factory.getIcon("error"); //$NON-NLS-1$
-
- EditorsPlugin.getDefault().addResourceChangedListener(mFrameworkResourceChangeListener);
+
+ AdtPlugin.getDefault().addResourceChangedListener(mFrameworkResourceChangeListener);
}
-
+
// ------------------------------------
// Methods overridden from base classes
//------------------------------------
-
+
@Override
public void createPartControl(Composite parent) {
mParent = parent;
@@ -237,13 +267,13 @@
GridData gd;
mClipboard = new Clipboard(parent.getDisplay());
-
+
parent.setLayout(gl = new GridLayout(1, false));
gl.marginHeight = gl.marginWidth = 0;
-
+
// create the top part for the configuration control
int cols = 10;
-
+
Composite topParent = new Composite(parent, SWT.NONE);
topParent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
topParent.setLayout(gl = new GridLayout(cols, false));
@@ -339,9 +369,9 @@
@Override
public void widgetSelected(SelectionEvent e) {
onOrientationChange();
- }
+ }
});
-
+
new Label(topParent, SWT.NONE).setText("Density");
mDensityIcon = createControlComposite(topParent, true /* grab_horizontal */);
mDensity = new Text(mDensityIcon.getParent(), SWT.BORDER);
@@ -437,7 +467,7 @@
gl.marginWidth = gl.marginHeight = 0;
labelParent.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
gd.horizontalSpan = cols;
-
+
new Label(labelParent, SWT.NONE).setText("Editing config:");
mCurrentLayoutLabel = new Label(labelParent, SWT.NONE);
mCurrentLayoutLabel.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
@@ -449,7 +479,7 @@
sizeParent.setLayout(gl = new GridLayout(3, false));
gl.marginWidth = gl.marginHeight = 0;
gl.horizontalSpacing = 0;
-
+
mSize1 = new Text(sizeParent, SWT.BORDER);
mSize1.setLayoutData(gd = new GridData());
gd.widthHint = 30;
@@ -457,11 +487,11 @@
mSize2 = new Text(sizeParent, SWT.BORDER);
mSize2.setLayoutData(gd = new GridData());
gd.widthHint = 30;
-
+
DimensionVerifier verifier = new DimensionVerifier();
mSize1.addVerifyListener(verifier);
mSize2.addVerifyListener(verifier);
-
+
SelectionListener sl = new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
onSizeChange();
@@ -470,7 +500,7 @@
onSizeChange();
}
};
-
+
mSize1.addSelectionListener(sl);
mSize2.addSelectionListener(sl);
@@ -488,7 +518,7 @@
separator.setLayoutData(gd = new GridData(
GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL));
gd.heightHint = 0;
-
+
mThemeCombo = new Combo(labelParent, SWT.READ_ONLY | SWT.DROP_DOWN);
mThemeCombo.setEnabled(false);
updateUIFromResources();
@@ -521,7 +551,7 @@
}
}
});
-
+
// create a new composite that will contain the standard editor controls.
Composite editorParent = new Composite(parent, SWT.NONE);
editorParent.setLayoutData(new GridData(GridData.FILL_BOTH));
@@ -532,28 +562,31 @@
@Override
public void dispose() {
if (mFrameworkResourceChangeListener != null) {
- EditorsPlugin.getDefault().removeResourceChangedListener(
+ AdtPlugin.getDefault().removeResourceChangedListener(
mFrameworkResourceChangeListener);
mFrameworkResourceChangeListener = null;
}
-
+
LayoutReloadMonitor.getMonitor().removeListener(mEditedFile.getProject(), this);
if (mClipboard != null) {
mClipboard.dispose();
mClipboard = null;
}
-
+
super.dispose();
}
-
+
/* (non-Javadoc)
* Creates the palette root.
*/
+ @Override
protected PaletteRoot getPaletteRoot() {
- return PaletteFactory.createPaletteRoot();
+ mPaletteRoot = PaletteFactory.createPaletteRoot(mPaletteRoot,
+ mLayoutEditor.getTargetData());
+ return mPaletteRoot;
}
-
+
public Clipboard getClipboard() {
return mClipboard;
}
@@ -577,22 +610,60 @@
firePropertyChange(PROP_DIRTY);
}
+ @Override
+ protected void configurePaletteViewer() {
+ super.configurePaletteViewer();
+
+ // Create a drag source listener on an edit part that is a viewer.
+ // What this does is use DND with a TemplateTransfer type which is actually
+ // the PaletteTemplateEntry held in the PaletteRoot.
+ TemplateTransferDragSourceListener dragSource =
+ new TemplateTransferDragSourceListener(getPaletteViewer());
+
+ // Create a drag source on the palette viewer.
+ // See the drag target associated with the GraphicalViewer in configureGraphicalViewer.
+ getPaletteViewer().addDragSourceListener(dragSource);
+ }
+
/* (non-javadoc)
* Configure the graphical viewer before it receives its contents.
*/
@Override
protected void configureGraphicalViewer() {
super.configureGraphicalViewer();
-
+
GraphicalViewer viewer = getGraphicalViewer();
viewer.setEditPartFactory(new UiElementsEditPartFactory(mParent.getDisplay()));
viewer.setRootEditPart(new ScalableFreeformRootEditPart());
- // TODO: viewer.setKeyHandler()
- // TODO: custom ContextMenuProvider => viewer.setContextMenu & registerContextMenu
+ // Disable the following -- we don't drag *from* the GraphicalViewer yet:
+ // viewer.addDragSourceListener(new TemplateTransferDragSourceListener(viewer));
+
+ viewer.addDropTargetListener(new DropListener(viewer));
+ }
+
+ class DropListener extends TemplateTransferDropTargetListener {
+ public DropListener(EditPartViewer viewer) {
+ super(viewer);
+ }
- viewer.addDragSourceListener(new TemplateTransferDragSourceListener(viewer));
- viewer.addDropTargetListener(new TemplateTransferDropTargetListener(viewer));
+ // TODO explain
+ @Override
+ protected CreationFactory getFactory(final Object template) {
+ return new CreationFactory() {
+ public Object getNewObject() {
+ // We don't know the newly created EditPart since "creating" new
+ // elements is done by ElementCreateCommand.execute() directly by
+ // manipulating the XML elements..
+ return null;
+ }
+
+ public Object getObjectType() {
+ return template;
+ }
+
+ };
+ }
}
/* (non-javadoc)
@@ -602,31 +673,184 @@
protected void initializeGraphicalViewer() {
GraphicalViewer viewer = getGraphicalViewer();
viewer.setContents(getModel());
-
+
IEditorInput input = getEditorInput();
if (input instanceof FileEditorInput) {
FileEditorInput fileInput = (FileEditorInput)input;
mEditedFile = fileInput.getFile();
-
+
updateUIFromResources();
LayoutReloadMonitor.getMonitor().addListener(mEditedFile.getProject(), this);
} else {
// really this shouldn't happen! Log it in case it happens
mEditedFile = null;
- EditorsPlugin.log(IStatus.ERROR, "Input is not of type FileEditorInput: %1$s",
+ AdtPlugin.log(IStatus.ERROR, "Input is not of type FileEditorInput: %1$s",
input.toString());
}
}
+ /* (non-javadoc)
+ * Sets the graphicalViewer for this EditorPart.
+ * @param viewer the graphical viewer
+ */
+ @Override
+ protected void setGraphicalViewer(GraphicalViewer viewer) {
+ super.setGraphicalViewer(viewer);
+
+ // TODO: viewer.setKeyHandler()
+ viewer.setContextMenu(createContextMenu(viewer));
+ }
+
+ /**
+ * Used by LayoutEditor.UiEditorActions.selectUiNode to select a new UI Node
+ * created by {@link ElementCreateCommand#execute()}.
+ *
+ * @param uiNodeModel The {@link UiElementNode} to select.
+ */
+ public void selectModel(UiElementNode uiNodeModel) {
+ GraphicalViewer viewer = getGraphicalViewer();
+
+ // Give focus to the graphical viewer (in case the outline has it)
+ viewer.getControl().forceFocus();
+
+ Object editPart = viewer.getEditPartRegistry().get(uiNodeModel);
+
+ if (editPart instanceof EditPart) {
+ viewer.select((EditPart)editPart);
+ }
+ }
+
+
//--------------
// Local methods
//--------------
-
+
public LayoutEditor getLayoutEditor() {
return mLayoutEditor;
}
+ private MenuManager createContextMenu(GraphicalViewer viewer) {
+ MenuManager menuManager = new MenuManager();
+ menuManager.setRemoveAllWhenShown(true);
+ menuManager.addMenuListener(new ActionMenuListener(viewer));
+
+ return menuManager;
+ }
+
+ private class ActionMenuListener implements IMenuListener {
+ private final GraphicalViewer mViewer;
+
+ public ActionMenuListener(GraphicalViewer viewer) {
+ mViewer = viewer;
+ }
+
+ /**
+ * The menu is about to be shown. The menu manager has already been
+ * requested to remove any existing menu item. This method gets the
+ * tree selection and if it is of the appropriate type it re-creates
+ * the necessary actions.
+ */
+ public void menuAboutToShow(IMenuManager manager) {
+ ArrayList<UiElementNode> selected = new ArrayList<UiElementNode>();
+
+ // filter selected items and only keep those we can handle
+ for (Object obj : mViewer.getSelectedEditParts()) {
+ if (obj instanceof UiElementEditPart) {
+ UiElementEditPart part = (UiElementEditPart) obj;
+ UiElementNode uiNode = part.getUiNode();
+ if (uiNode != null) {
+ selected.add(uiNode);
+ }
+ }
+ }
+
+ if (selected.size() > 0) {
+ doCreateMenuAction(manager, mViewer, selected);
+ }
+ }
+ }
+
+ private void doCreateMenuAction(IMenuManager manager,
+ final GraphicalViewer viewer,
+ final ArrayList<UiElementNode> selected) {
+ if (selected != null) {
+ boolean hasXml = false;
+ for (UiElementNode uiNode : selected) {
+ if (uiNode.getXmlNode() != null) {
+ hasXml = true;
+ break;
+ }
+ }
+
+ if (hasXml) {
+ manager.add(new CopyCutAction(mLayoutEditor, getClipboard(),
+ null, selected, true /* cut */));
+ manager.add(new CopyCutAction(mLayoutEditor, getClipboard(),
+ null, selected, false /* cut */));
+
+ // Can't paste with more than one element selected (the selection is the target)
+ if (selected.size() <= 1) {
+ // Paste is not valid if it would add a second element on a terminal element
+ // which parent is a document -- an XML document can only have one child. This
+ // means paste is valid if the current UI node can have children or if the
+ // parent is not a document.
+ UiElementNode ui_root = selected.get(0).getUiRoot();
+ if (ui_root.getDescriptor().hasChildren() ||
+ !(ui_root.getUiParent() instanceof UiDocumentNode)) {
+ manager.add(new PasteAction(mLayoutEditor, getClipboard(),
+ selected.get(0)));
+ }
+ }
+ manager.add(new Separator());
+ }
+ }
+
+ // Append "add" and "remove" actions. They do the same thing as the add/remove
+ // buttons on the side.
+ IconFactory factory = IconFactory.getInstance();
+
+ final UiEditorActions uiActions = mLayoutEditor.getUiEditorActions();
+
+ // "Add" makes sense only if there's 0 or 1 item selected since the
+ // one selected item becomes the target.
+ if (selected == null || selected.size() <= 1) {
+ manager.add(new Action("Add...", factory.getImageDescriptor("add")) { //$NON-NLS-2$
+ @Override
+ public void run() {
+ UiElementNode node = selected != null && selected.size() > 0 ? selected.get(0)
+ : null;
+ uiActions.doAdd(node, viewer.getControl().getShell());
+ }
+ });
+ }
+
+ if (selected != null) {
+ manager.add(new Action("Remove", factory.getImageDescriptor("delete")) { //$NON-NLS-2$
+ @Override
+ public void run() {
+ uiActions.doRemove(selected, viewer.getControl().getShell());
+ }
+ });
+
+ manager.add(new Separator());
+
+ manager.add(new Action("Up", factory.getImageDescriptor("up")) { //$NON-NLS-2$
+ @Override
+ public void run() {
+ uiActions.doUp(selected);
+ }
+ });
+ manager.add(new Action("Down", factory.getImageDescriptor("down")) { //$NON-NLS-2$
+ @Override
+ public void run() {
+ uiActions.doDown(selected);
+ }
+ });
+ }
+
+ }
+
/**
* Sets the UI for the edition of a new file.
* @param configuration the configuration of the new file.
@@ -669,7 +893,7 @@
s1 = s2;
s2 = tmp;
}
-
+
switch (orientation) {
default:
case PORTRAIT:
@@ -680,6 +904,105 @@
return new Rectangle(0, 0, s1, s1);
}
}
+
+ /**
+ * Renders an Android View described by a {@link ViewElementDescriptor}.
+ * <p/>This uses the <code>wrap_content</code> mode for both <code>layout_width</code> and
+ * <code>layout_height</code>, and use the class name for the <code>text</code> attribute.
+ * @param descriptor the descriptor for the class to render.
+ * @return an ImageData containing the rendering or <code>null</code> if rendering failed.
+ */
+ public ImageData renderWidget(ViewElementDescriptor descriptor) {
+ if (mEditedFile == null) {
+ return null;
+ }
+
+ IAndroidTarget target = Sdk.getCurrent().getTarget(mEditedFile.getProject());
+ if (target == null) {
+ return null;
+ }
+
+ AndroidTargetData data = Sdk.getCurrent().getTargetData(target);
+ if (data == null) {
+ return null;
+ }
+
+ LayoutBridge bridge = data.getLayoutBridge();
+
+ if (bridge.bridge != null) { // bridge can never be null.
+ ResourceManager resManager = ResourceManager.getInstance();
+
+ ProjectCallback projectCallback = null;
+ Map<String, Map<String, IResourceValue>> configuredProjectResources = null;
+ if (mEditedFile != null) {
+ ProjectResources projectRes = resManager.getProjectResources(
+ mEditedFile.getProject());
+ projectCallback = new ProjectCallback(bridge.classLoader,
+ projectRes, mEditedFile.getProject());
+
+ // get the configured resources for the project
+ // get the resources of the file's project.
+ if (mConfiguredProjectRes == null && projectRes != null) {
+ // make sure they are loaded
+ projectRes.loadAll();
+
+ // get the project resource values based on the current config
+ mConfiguredProjectRes = projectRes.getConfiguredResources(mCurrentConfig);
+ }
+
+ configuredProjectResources = mConfiguredProjectRes;
+ } else {
+ // we absolutely need a Map of configured project resources.
+ configuredProjectResources = new HashMap<String, Map<String, IResourceValue>>();
+ }
+
+ // get the framework resources
+ Map<String, Map<String, IResourceValue>> frameworkResources =
+ getConfiguredFrameworkResources();
+
+ if (configuredProjectResources != null && frameworkResources != null) {
+ // get the selected theme
+ int themeIndex = mThemeCombo.getSelectionIndex();
+ if (themeIndex != -1) {
+ String theme = mThemeCombo.getItem(themeIndex);
+
+ // change the string if it's a custom theme to make sure we can
+ // differentiate them
+ if (themeIndex >= mPlatformThemeCount) {
+ theme = "*" + theme; //$NON-NLS-1$
+ }
+
+ // Render a single object as described by the ViewElementDescriptor.
+ WidgetPullParser parser = new WidgetPullParser(descriptor);
+ ILayoutResult result = bridge.bridge.computeLayout(parser,
+ null /* projectKey */,
+ 300 /* width */, 300 /* height */, theme,
+ configuredProjectResources, frameworkResources, projectCallback,
+ null /* logger */);
+
+ // update the UiElementNode with the layout info.
+ if (result.getSuccess() == ILayoutResult.SUCCESS) {
+ BufferedImage largeImage = result.getImage();
+
+ // we need to resize it to the actual widget size, and convert it into
+ // an SWT image object.
+ int width = result.getRootView().getRight();
+ int height = result.getRootView().getBottom();
+ Raster raster = largeImage.getData(new java.awt.Rectangle(width, height));
+ int[] imageDataBuffer = ((DataBufferInt)raster.getDataBuffer()).getData();
+
+ ImageData imageData = new ImageData(width, height, 32,
+ new PaletteData(0x00FF0000, 0x0000FF00, 0x000000FF));
+
+ imageData.setPixels(0, 0, imageDataBuffer.length, imageDataBuffer, 0);
+
+ return imageData;
+ }
+ }
+ }
+ }
+ return null;
+ }
/**
* Reloads this editor, by getting the new model from the {@link LayoutEditor}.
@@ -690,41 +1013,41 @@
IEditorInput input = mLayoutEditor.getEditorInput();
setInput(input);
-
+
if (input instanceof FileEditorInput) {
FileEditorInput fileInput = (FileEditorInput)input;
mEditedFile = fileInput.getFile();
} else {
// really this shouldn't happen! Log it in case it happens
mEditedFile = null;
- EditorsPlugin.log(IStatus.ERROR, "Input is not of type FileEditorInput: %1$s",
+ AdtPlugin.log(IStatus.ERROR, "Input is not of type FileEditorInput: %1$s",
input.toString());
}
}
-
+
/**
* Update the layout editor when the Xml model is changed.
*/
void onXmlModelChanged() {
GraphicalViewer viewer = getGraphicalViewer();
-
+
// try to preserve the selection before changing the content
SelectionManager selMan = viewer.getSelectionManager();
ISelection selection = selMan.getSelection();
-
+
try {
viewer.setContents(getModel());
} finally {
selMan.setSelection(selection);
- }
-
+ }
+
if (mLayoutEditor.isGraphicalEditorActive()) {
recomputeLayout();
} else {
mNeedsRecompute = true;
}
}
-
+
/**
* Update the UI controls state with a given {@link FolderConfiguration}.
* <p/>If a qualifier is not present in the {@link FolderConfiguration} object, the UI control
@@ -745,7 +1068,7 @@
} else if (mCountry.getText().length() > 0) {
mCountryIcon.setImage(mWarningImage);
}
-
+
mNetworkIcon.setImage(mMatchImage);
NetworkCodeQualifier networkQualifier = config.getNetworkCodeQualifier();
if (networkQualifier != null) {
@@ -754,7 +1077,7 @@
} else if (mNetwork.getText().length() > 0) {
mNetworkIcon.setImage(mWarningImage);
}
-
+
mLanguageIcon.setImage(mMatchImage);
LanguageQualifier languageQualifier = config.getLanguageQualifier();
if (languageQualifier != null) {
@@ -763,7 +1086,7 @@
} else if (mLanguage.getText().length() > 0) {
mLanguageIcon.setImage(mWarningImage);
}
-
+
mRegionIcon.setImage(mMatchImage);
RegionQualifier regionQualifier = config.getRegionQualifier();
if (regionQualifier != null) {
@@ -772,7 +1095,7 @@
} else if (mRegion.getText().length() > 0) {
mRegionIcon.setImage(mWarningImage);
}
-
+
mOrientationIcon.setImage(mMatchImage);
ScreenOrientationQualifier orientationQualifier = config.getScreenOrientationQualifier();
if (orientationQualifier != null) {
@@ -782,7 +1105,7 @@
} else if (mOrientation.getSelectionIndex() != 0) {
mOrientationIcon.setImage(mWarningImage);
}
-
+
mDensityIcon.setImage(mMatchImage);
PixelDensityQualifier densityQualifier = config.getPixelDensityQualifier();
if (densityQualifier != null) {
@@ -791,7 +1114,7 @@
} else if (mDensity.getText().length() > 0) {
mDensityIcon.setImage(mWarningImage);
}
-
+
mTouchIcon.setImage(mMatchImage);
TouchScreenQualifier touchQualifier = config.getTouchTypeQualifier();
if (touchQualifier != null) {
@@ -800,7 +1123,7 @@
} else if (mTouch.getSelectionIndex() != 0) {
mTouchIcon.setImage(mWarningImage);
}
-
+
mKeyboardIcon.setImage(mMatchImage);
KeyboardStateQualifier keyboardQualifier = config.getKeyboardStateQualifier();
if (keyboardQualifier != null) {
@@ -818,7 +1141,7 @@
} else if (mTextInput.getSelectionIndex() != 0) {
mTextInputIcon.setImage(mWarningImage);
}
-
+
mNavigationIcon.setImage(mMatchImage);
NavigationMethodQualifier navigationQualifiter = config.getNavigationMethodQualifier();
if (navigationQualifiter != null) {
@@ -828,7 +1151,7 @@
} else if (mNavigation.getSelectionIndex() != 0) {
mNavigationIcon.setImage(mWarningImage);
}
-
+
mSizeIcon.setImage(mMatchImage);
ScreenDimensionQualifier sizeQualifier = config.getScreenDimensionQualifier();
if (sizeQualifier != null) {
@@ -838,7 +1161,7 @@
} else if (mSize1.getText().length() > 0 && mSize2.getText().length() > 0) {
mSizeIcon.setImage(mWarningImage);
}
-
+
// update the string showing the folder name
String current = config.toDisplayString();
mCurrentLayoutLabel.setText(current != null ? current : "(Default)");
@@ -927,6 +1250,10 @@
return mLayoutEditor.getUiRootNode();
}
+ void reloadPalette() {
+ PaletteFactory.createPaletteRoot(mPaletteRoot, mLayoutEditor.getTargetData());
+ }
+
private void onCountryCodeChange() {
// because mCountry triggers onCountryCodeChange at each modification, calling setText()
// will trigger notifications, and we don't want that.
@@ -936,7 +1263,7 @@
// update the current config
String value = mCountry.getText();
-
+
// empty string, means no qualifier.
if (value.length() == 0) {
mCurrentConfig.setCountryCodeQualifier(null);
@@ -959,7 +1286,7 @@
mCountryIcon.setImage(mErrorImage);
}
}
-
+
// look for a file to open/create
onConfigurationChange();
}
@@ -973,7 +1300,7 @@
// update the current config
String value = mNetwork.getText();
-
+
// empty string, means no qualifier.
if (value.length() == 0) {
mCurrentConfig.setNetworkCodeQualifier(null);
@@ -996,7 +1323,7 @@
mNetworkIcon.setImage(mErrorImage);
}
}
-
+
// look for a file to open/create
onConfigurationChange();
}
@@ -1013,9 +1340,9 @@
// update the current config
String value = mLanguage.getText();
-
+
updateRegionUi(null /* projectResources */, null /* frameworkResources */);
-
+
// empty string, means no qualifier.
if (value.length() == 0) {
mCurrentConfig.setLanguageQualifier(null);
@@ -1034,11 +1361,11 @@
mLanguageIcon.setImage(mErrorImage);
}
}
-
+
// look for a file to open/create
onConfigurationChange();
}
-
+
private void onRegionChange() {
// because mRegion triggers onRegionChange at each modification, the filling
// of the combo with data will trigger notifications, and we don't want that.
@@ -1048,7 +1375,7 @@
// update the current config
String value = mRegion.getText();
-
+
// empty string, means no qualifier.
if (value.length() == 0) {
mCurrentConfig.setRegionQualifier(null);
@@ -1067,11 +1394,11 @@
mRegionIcon.setImage(mErrorImage);
}
}
-
+
// look for a file to open/create
onConfigurationChange();
}
-
+
private void onOrientationChange() {
// update the current config
int index = mOrientation.getSelectionIndex();
@@ -1081,11 +1408,11 @@
} else {
mCurrentConfig.setScreenOrientationQualifier(null);
}
-
+
// look for a file to open/create
onConfigurationChange();
}
-
+
private void onDensityChange() {
// because mDensity triggers onDensityChange at each modification, calling setText()
// will trigger notifications, and we don't want that.
@@ -1095,7 +1422,7 @@
// update the current config
String value = mDensity.getText();
-
+
// empty string, means no qualifier.
if (value.length() == 0) {
mCurrentConfig.setPixelDensityQualifier(null);
@@ -1122,7 +1449,7 @@
// look for a file to open/create
onConfigurationChange();
}
-
+
private void onTouchChange() {
// update the current config
int index = mTouch.getSelectionIndex();
@@ -1132,7 +1459,7 @@
} else {
mCurrentConfig.setTouchTypeQualifier(null);
}
-
+
// look for a file to open/create
onConfigurationChange();
}
@@ -1146,11 +1473,11 @@
} else {
mCurrentConfig.setKeyboardStateQualifier(null);
}
-
+
// look for a file to open/create
onConfigurationChange();
}
-
+
private void onTextInputChange() {
// update the current config
int index = mTextInput.getSelectionIndex();
@@ -1160,11 +1487,11 @@
} else {
mCurrentConfig.setTextInputMethodQualifier(null);
}
-
+
// look for a file to open/create
onConfigurationChange();
}
-
+
private void onNavigationChange() {
// update the current config
int index = mNavigation.getSelectionIndex();
@@ -1174,11 +1501,11 @@
} else {
mCurrentConfig.setNavigationMethodQualifier(null);
}
-
+
// look for a file to open/create
onConfigurationChange();
}
-
+
private void onSizeChange() {
// because mSize1 and mSize2 trigger onSizeChange at each modification, calling setText()
// will trigger notifications, and we don't want that.
@@ -1189,7 +1516,7 @@
// update the current config
String size1 = mSize1.getText();
String size2 = mSize2.getText();
-
+
// if only one of the strings is empty, do nothing
if ((size1.length() == 0) ^ (size2.length() == 0)) {
mSizeIcon.setImage(mErrorImage);
@@ -1209,12 +1536,12 @@
return;
}
}
-
+
// look for a file to open/create
onConfigurationChange();
}
-
+
/**
* Looks for a file matching the new {@link FolderConfiguration} and attempts to open it.
* <p/>If there is no match, notify the user.
@@ -1237,7 +1564,7 @@
ResourceFolderType.LAYOUT,
mCurrentConfig);
}
-
+
if (match != null) {
if (match.getFile().equals(mEditedFile) == false) {
try {
@@ -1279,7 +1606,7 @@
showErrorInEditor(message);
}
}
-
+
private void onThemeChange() {
int themeIndex = mThemeCombo.getSelectionIndex();
if (themeIndex != -1) {
@@ -1314,10 +1641,10 @@
// create the label
Label icon = new Label(composite, SWT.NONE);
icon.setImage(mMatchImage);
-
+
return icon;
}
-
+
/**
* Recomputes the layout with the help of layoutlib.
*/
@@ -1328,7 +1655,7 @@
// return false;
if (mEditedFile.exists() == false) {
String message = String.format("Resource '%1$s' does not exist.",
- mEditedFile.getFullPath().toString());
+ mEditedFile.getFullPath().toString());
showErrorInEditor(message);
@@ -1339,126 +1666,156 @@
if (mEditedFile.isSynchronized(IResource.DEPTH_ZERO) == false) {
String message = String.format("%1$s is out of sync. Please refresh.",
- mEditedFile.getName());
+ mEditedFile.getName());
showErrorInEditor(message);
// also print it in the error console.
- EditorsPlugin.printErrorToConsole(iProject.getName(), message);
+ AdtPlugin.printErrorToConsole(iProject.getName(), message);
return;
}
- // check there is actually a model (maybe the file is empty).
- UiDocumentNode model = getModel();
-
- if (model.getUiChildren().size() == 0) {
- showErrorInEditor("No Xml content. Go to the Outline view and add nodes.");
- return;
- }
-
- EditorsPlugin plugin = EditorsPlugin.getDefault();
- LayoutBridge bridge = plugin.getLayoutBridge();
-
- if (bridge.bridge != null) { // bridge can never be null.
- ResourceManager resManager = ResourceManager.getInstance();
-
- ProjectResources projectRes = resManager.getProjectResources(iProject);
- if (projectRes == null) {
+ Sdk currentSdk = Sdk.getCurrent();
+ if (currentSdk != null) {
+ IAndroidTarget target = currentSdk.getTarget(mEditedFile.getProject());
+ if (target == null) {
+ showErrorInEditor("The project target is not set.");
+ return;
+ }
+
+ AndroidTargetData data = currentSdk.getTargetData(target);
+ if (data == null) {
+ // It can happen that the workspace refreshes while the SDK is loading its
+ // data, which could trigger a redraw of the opened layout if some resources
+ // changed while Eclipse is closed.
+ // In this case data could be null, but this is not an error.
+ // We can just silently return, as all the opened editors are automatically
+ // refreshed once the SDK finishes loading.
+ if (AdtPlugin.getDefault().getSdkLoadStatus(null) != LoadStatus.LOADING) {
+ showErrorInEditor(String.format(
+ "The project target (%s) was not properly loaded.",
+ target.getName()));
+ }
return;
}
- // get the resources of the file's project.
- if (mConfiguredProjectRes == null) {
- // make sure they are loaded
- projectRes.loadAll();
+ // check there is actually a model (maybe the file is empty).
+ UiDocumentNode model = getModel();
- // get the project resource values based on the current config
- mConfiguredProjectRes = projectRes.getConfiguredResources(mCurrentConfig);
+ if (model.getUiChildren().size() == 0) {
+ showErrorInEditor("No Xml content. Go to the Outline view and add nodes.");
+ return;
}
- // get the framework resources
- Map<String, Map<String, IResourceValue>> frameworkResources =
- getConfiguredFrameworkResources();
+ LayoutBridge bridge = data.getLayoutBridge();
- if (mConfiguredProjectRes != null && frameworkResources != null) {
- if (mProjectCallback == null) {
- mProjectCallback = new ProjectCallback(
- plugin.getLayoutlibBridgeClassLoader(), projectRes, iProject);
+ if (bridge.bridge != null) { // bridge can never be null.
+ ResourceManager resManager = ResourceManager.getInstance();
+
+ ProjectResources projectRes = resManager.getProjectResources(iProject);
+ if (projectRes == null) {
+ return;
}
-
- if (mLogger == null) {
- mLogger = new ILayoutLog() {
- public void error(String message) {
- EditorsPlugin.printErrorToConsole(mEditedFile.getName(), message);
- }
-
- public void error(Throwable error) {
- String message = error.getMessage();
- if (message == null) {
- message = error.getClass().getName();
+
+ // get the resources of the file's project.
+ if (mConfiguredProjectRes == null) {
+ // make sure they are loaded
+ projectRes.loadAll();
+
+ // get the project resource values based on the current config
+ mConfiguredProjectRes = projectRes.getConfiguredResources(mCurrentConfig);
+ }
+
+ // get the framework resources
+ Map<String, Map<String, IResourceValue>> frameworkResources =
+ getConfiguredFrameworkResources();
+
+ if (mConfiguredProjectRes != null && frameworkResources != null) {
+ if (mProjectCallback == null) {
+ mProjectCallback = new ProjectCallback(
+ bridge.classLoader, projectRes, iProject);
+ }
+
+ if (mLogger == null) {
+ mLogger = new ILayoutLog() {
+ public void error(String message) {
+ AdtPlugin.printErrorToConsole(mEditedFile.getName(), message);
}
-
- PrintStream ps = new PrintStream(EditorsPlugin.getErrorStream());
- error.printStackTrace(ps);
- }
-
- public void warning(String message) {
- EditorsPlugin.printToConsole(mEditedFile.getName(), message);
- }
- };
- }
-
- // get the selected theme
- int themeIndex = mThemeCombo.getSelectionIndex();
- if (themeIndex != -1) {
- String theme = mThemeCombo.getItem(themeIndex);
-
- // change the string if it's a custom theme to make sure we can
- // differentiate them
- if (themeIndex >= mPlatformThemeCount) {
- theme = "*" + theme; //$NON-NLS-1$
+
+ public void error(Throwable error) {
+ String message = error.getMessage();
+ if (message == null) {
+ message = error.getClass().getName();
+ }
+
+ PrintStream ps = new PrintStream(AdtPlugin.getErrorStream());
+ error.printStackTrace(ps);
+ }
+
+ public void warning(String message) {
+ AdtPlugin.printToConsole(mEditedFile.getName(), message);
+ }
+ };
}
-
- // Compute the layout
- UiElementPullParser parser = new UiElementPullParser(getModel());
- Rectangle rect = getBounds();
- ILayoutResult result = bridge.bridge.computeLayout(parser, iProject,
- rect.width, rect.height, theme,
- mConfiguredProjectRes, frameworkResources, mProjectCallback,
- mLogger);
-
- // update the UiElementNode with the layout info.
- if (result.getSuccess() == ILayoutResult.SUCCESS) {
- model.setEditData(result.getImage());
-
- updateNodeWithBounds(result.getRootView());
- } else {
- String message = result.getErrorMessage();
-
- // Reset the edit data for all the nodes.
- resetNodeBounds(model);
-
- if (message != null) {
- // set the error in the top element.
- model.setEditData(message);
+
+ // get the selected theme
+ int themeIndex = mThemeCombo.getSelectionIndex();
+ if (themeIndex != -1) {
+ String theme = mThemeCombo.getItem(themeIndex);
+
+ // change the string if it's a custom theme to make sure we can
+ // differentiate them
+ if (themeIndex >= mPlatformThemeCount) {
+ theme = "*" + theme; //$NON-NLS-1$
}
+
+ // Compute the layout
+ UiElementPullParser parser = new UiElementPullParser(getModel());
+ Rectangle rect = getBounds();
+ ILayoutResult result = bridge.bridge.computeLayout(parser,
+ iProject /* projectKey */,
+ rect.width, rect.height, theme,
+ mConfiguredProjectRes, frameworkResources, mProjectCallback,
+ mLogger);
+
+ // update the UiElementNode with the layout info.
+ if (result.getSuccess() == ILayoutResult.SUCCESS) {
+ model.setEditData(result.getImage());
+
+ updateNodeWithBounds(result.getRootView());
+ } else {
+ String message = result.getErrorMessage();
+
+ // Reset the edit data for all the nodes.
+ resetNodeBounds(model);
+
+ if (message != null) {
+ // set the error in the top element.
+ model.setEditData(message);
+ }
+ }
+
+ model.refreshUi();
}
-
- model.refreshUi();
}
+ } else {
+ // SDK is loaded but not the layout library!
+ String message = null;
+ // check whether the bridge managed to load, or not
+ if (bridge.status == LoadStatus.LOADING) {
+ message = String.format(
+ "Eclipse is loading framework information and the Layout library from the SDK folder.\n%1$s will refresh automatically once the process is finished.",
+ mEditedFile.getName());
+ } else {
+ message = String.format("Eclipse failed to load the framework information and the Layout library!");
+ }
+ showErrorInEditor(message);
}
} else {
- String message = null;
+ String message = String.format(
+ "Eclipse is loading the SDK.\n%1$s will refresh automatically once the process is finished.",
+ mEditedFile.getName());
- // check whether the bridge managed to load, or not
- if (bridge.status == LayoutBridge.LoadStatus.LOADING) {
- message = String.format(
- "Eclipse is loading framework information and the Layout library from the SDK folder.\n%1$s will refresh automatically once the process is finished.",
- mEditedFile.getName());
- } else {
- message = String.format("Eclipse failed to load the framework information and the Layout library!");
- }
-
showErrorInEditor(message);
}
} finally {
@@ -1482,10 +1839,10 @@
model.refreshUi();
}
-
+
private void resetNodeBounds(UiElementNode node) {
node.setEditData(null);
-
+
List<UiElementNode> children = node.getUiChildren();
for (UiElementNode child : children) {
resetNodeBounds(child);
@@ -1499,10 +1856,10 @@
if (viewKey instanceof UiElementNode) {
Rectangle bounds = new Rectangle(r.getLeft(), r.getTop(),
r.getRight()-r.getLeft(), r.getBottom() - r.getTop());
-
+
((UiElementNode)viewKey).setEditData(bounds);
}
-
+
// and then its children.
ILayoutViewInfo[] children = r.getChildren();
if (children != null) {
@@ -1512,11 +1869,11 @@
}
}
}
-
+
/*
* (non-Javadoc)
* @see com.android.ide.eclipse.editors.layout.LayoutReloadMonitor.ILayoutReloadListener#reloadLayout(boolean, boolean, boolean)
- *
+ *
* Called when the file changes triggered a redraw of the layout
*/
public void reloadLayout(boolean codeChange, boolean rChange, boolean resChange) {
@@ -1525,19 +1882,25 @@
if (resChange) {
recompute = true;
- // TODO: differentiate between single and multi resource file changed, and whether the resource change affects the cache.
+ // TODO: differentiate between single and multi resource file changed, and whether the resource change affects the cache.
// force a reparse in case a value XML file changed.
mConfiguredProjectRes = null;
-
- // clear the cache in the bridge in case a bitmap/9-patch changed.
- EditorsPlugin plugin = EditorsPlugin.getDefault();
- LayoutBridge bridge = plugin.getLayoutBridge();
- if (bridge.bridge != null) {
- bridge.bridge.clearCaches(mEditedFile.getProject());
+ // clear the cache in the bridge in case a bitmap/9-patch changed.
+ IAndroidTarget target = Sdk.getCurrent().getTarget(mEditedFile.getProject());
+ if (target != null) {
+
+ AndroidTargetData data = Sdk.getCurrent().getTargetData(target);
+ if (data != null) {
+ LayoutBridge bridge = data.getLayoutBridge();
+
+ if (bridge.bridge != null) {
+ bridge.bridge.clearCaches(mEditedFile.getProject());
+ }
+ }
}
-
+
mParent.getDisplay().asyncExec(mUiUpdateFromResourcesRunnable);
}
@@ -1548,7 +1911,7 @@
recompute = true;
}
}
-
+
if (recompute) {
mParent.getDisplay().asyncExec(mConditionalRecomputeRunnable);
}
@@ -1558,11 +1921,19 @@
* Responds to a page change that made the Graphical editor page the activated page.
*/
void activated() {
+ mActive = true;
if (mNeedsRecompute) {
recomputeLayout();
}
}
-
+
+ /**
+ * Responds to a page change that made the Graphical editor page the deactivated page
+ */
+ void deactivated() {
+ mActive = false;
+ }
+
/**
* Updates the UI from values in the resources, such as languages, regions, themes, etc...
* This must be called from the UI thread.
@@ -1570,8 +1941,8 @@
private void updateUIFromResources() {
ResourceManager manager = ResourceManager.getInstance();
-
- ProjectResources frameworkProject = manager.getFrameworkResources();
+
+ ProjectResources frameworkProject = getFrameworkResources();
mDisableUpdates = true;
@@ -1615,7 +1986,6 @@
mPlatformThemeCount = themes.size();
themes.clear();
}
-
// now get the languages from the framework.
Set<String> frameworkLanguages = frameworkProject.getLanguages();
if (frameworkLanguages != null) {
@@ -1627,7 +1997,7 @@
ProjectResources project = null;
if (mEditedFile != null) {
project = manager.getProjectResources(mEditedFile.getProject());
-
+
// in cases where the opened file is not linked to a project, this could be null.
if (project != null) {
// get the configured resources for the project
@@ -1706,7 +2076,7 @@
* This is done by making sure the parent is a theme.
* @param value the style to check
* @param styleMap the map of styles for the current project. Key is the style name.
- * @return
+ * @return True if the given <var>style</var> is a theme.
*/
private boolean isTheme(IResourceValue value, Map<String, IResourceValue> styleMap) {
if (value instanceof IStyleResourceValue) {
@@ -1767,15 +2137,15 @@
projectResources = ResourceManager.getInstance().getProjectResources(
mEditedFile.getProject());
}
-
+
if (frameworkResources == null) {
- frameworkResources = ResourceManager.getInstance().getFrameworkResources();
+ frameworkResources = getFrameworkResources();
}
-
+
String currentLanguage = mLanguage.getText();
-
+
Set<String> set = null;
-
+
if (projectResources != null) {
set = projectResources.getRegions(currentLanguage);
}
@@ -1803,10 +2173,10 @@
private Map<String, Map<String, IResourceValue>> getConfiguredFrameworkResources() {
if (mConfiguredFrameworkRes == null) {
- ProjectResources frameworkRes = ResourceManager.getInstance().getFrameworkResources();
+ ProjectResources frameworkRes = getFrameworkResources();
if (frameworkRes == null) {
- EditorsPlugin.log(IStatus.ERROR, "Failed to get ProjectResource for the framework");
+ AdtPlugin.log(IStatus.ERROR, "Failed to get ProjectResource for the framework");
}
// get the framework resource values based on the current config
@@ -1821,19 +2191,19 @@
* The synchronizer can be used to sync the selection of 2 or more EditPartViewers.
* <p/>
* This is changed from protected to public so that the outline can use it.
- *
+ *
* @return the synchronizer
*/
@Override
public SelectionSynchronizer getSelectionSynchronizer() {
return super.getSelectionSynchronizer();
}
-
+
/**
* Returns the edit domain.
* <p/>
* This is changed from protected to public so that the outline can use it.
- *
+ *
* @return the edit domain
*/
@Override
@@ -1865,10 +2235,9 @@
String message = String.format("File 'res/%1$s' is in the way!",
folderName);
- EditorsPlugin.displayError("Layout Creation", message);
+ AdtPlugin.displayError("Layout Creation", message);
- return new Status(IStatus.ERROR,
- AndroidConstants.EDITORS_PLUGIN_ID, message);
+ return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, message);
} else if (newLayoutFolder.exists() == false) {
// create it.
newLayoutFolder.mkdir();
@@ -1903,7 +2272,7 @@
mParent.getDisplay().asyncExec(new Runnable() {
public void run() {
onConfigurationChange();
- };
+ }
});
}
@@ -1941,16 +2310,16 @@
"Failed to create File 'res/%1$s/%2$s' : %3$s",
folderName, mEditedFile.getName(), e2.getMessage());
- EditorsPlugin.displayError("Layout Creation", message);
+ AdtPlugin.displayError("Layout Creation", message);
- return new Status(IStatus.ERROR, AndroidConstants.EDITORS_PLUGIN_ID,
+ return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
message, e2);
} catch (CoreException e2) {
String message = String.format(
"Failed to create File 'res/%1$s/%2$s' : %3$s",
folderName, mEditedFile.getName(), e2.getMessage());
- EditorsPlugin.displayError("Layout Creation", message);
+ AdtPlugin.displayError("Layout Creation", message);
return e2.getStatus();
}
@@ -1960,4 +2329,27 @@
}
}.schedule();
}
+
+ /**
+ * Returns a {@link ProjectResources} for the framework resources.
+ * @return the framework resources or null if not found.
+ */
+ private ProjectResources getFrameworkResources() {
+ if (mEditedFile != null) {
+ Sdk currentSdk = Sdk.getCurrent();
+ if (currentSdk != null) {
+ IAndroidTarget target = currentSdk.getTarget(mEditedFile.getProject());
+
+ if (target != null) {
+ AndroidTargetData data = currentSdk.getTargetData(target);
+
+ if (data != null) {
+ return data.getFrameworkResources();
+ }
+ }
+ }
+ }
+
+ return null;
+ }
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutConstants.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutConstants.java
new file mode 100644
index 0000000..d4ec5e1
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutConstants.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.editors.layout;
+
+/**
+ * A bunch of constants that map to either:
+ * <ul>
+ * <li>Android Layouts XML element names (Linear, Relative, Absolute, etc.)
+ * <li>Attributes for layout XML elements.
+ * <li>Values for attributes.
+ * </ul>
+ */
+public class LayoutConstants {
+
+ public static final String RELATIVE_LAYOUT = "RelativeLayout"; //$NON-NLS-1$
+ public static final String LINEAR_LAYOUT = "LinearLayout"; //$NON-NLS-1$
+ public static final String ABSOLUTE_LAYOUT = "AbsoluteLayout"; //$NON-NLS-1$
+
+ public static final String ATTR_TEXT = "text"; //$NON-NLS-1$
+ public static final String ATTR_ID = "id"; //$NON-NLS-1$
+
+ public static final String ATTR_LAYOUT_HEIGHT = "layout_height"; //$NON-NLS-1$
+ public static final String ATTR_LAYOUT_WIDTH = "layout_width"; //$NON-NLS-1$
+
+ public static final String ATTR_LAYOUT_ALIGN_PARENT_TOP = "layout_alignParentTop"; //$NON-NLS-1$
+ public static final String ATTR_LAYOUT_ALIGN_PARENT_BOTTOM = "layout_alignParentBottom"; //$NON-NLS-1$
+ public static final String ATTR_LAYOUT_ALIGN_PARENT_LEFT = "layout_alignParentLeft";//$NON-NLS-1$
+ public static final String ATTR_LAYOUT_ALIGN_PARENT_RIGHT = "layout_alignParentRight"; //$NON-NLS-1$
+
+ public static final String ATTR_LAYOUT_ALIGN_BASELINE = "layout_alignBaseline"; //$NON-NLS-1$
+
+ public static final String ATTR_LAYOUT_CENTER_VERTICAL = "layout_centerVertical"; //$NON-NLS-1$
+ public static final String ATTR_LAYOUT_CENTER_HORIZONTAL = "layout_centerHorizontal"; //$NON-NLS-1$
+
+ public static final String ATTR_LAYOUT_TO_RIGHT_OF = "layout_toRightOf"; //$NON-NLS-1$
+ public static final String ATTR_LAYOUT_TO_LEFT_OF = "layout_toLeftOf"; //$NON-NLS-1$
+
+ public static final String ATTR_LAYOUT_BELOW = "layout_below"; //$NON-NLS-1$
+ public static final String ATTR_LAYOUT_ABOVE = "layout_above"; //$NON-NLS-1$
+
+ public static final String ATTR_LAYOUT_Y = "layout_y"; //$NON-NLS-1$
+ public static final String ATTR_LAYOUT_X = "layout_x"; //$NON-NLS-1$
+
+ public static final String VALUE_WRAP_CONTENT = "wrap_content"; //$NON-NLS-1$
+ public static final String VALUE_FILL_PARENT = "fill_parent"; //$NON-NLS-1$
+ public static final String VALUE_TRUE = "true"; //$NON-NLS-1$
+ public static final String VALUE_N_DIP = "%ddip"; //$NON-NLS-1$
+
+ private LayoutConstants() {
+ }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutContentAssist.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutContentAssist.java
similarity index 86%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutContentAssist.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutContentAssist.java
index dfec17a..9f39495 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutContentAssist.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutContentAssist.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.layout;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.editors.AndroidContentAssist;
-import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
/**
* Content Assist Processor for /res/layout XML files
@@ -28,6 +28,6 @@
* Constructor for LayoutContentAssist
*/
public LayoutContentAssist() {
- super(LayoutDescriptors.getInstance().getDescriptor().getChildren());
+ super(AndroidTargetData.DESCRIPTOR_LAYOUT);
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutCreatorDialog.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutCreatorDialog.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutCreatorDialog.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutCreatorDialog.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java
similarity index 79%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java
index f1bedcb..880ee2b 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java
@@ -16,14 +16,17 @@
package com.android.ide.eclipse.editors.layout;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.EclipseUiHelper;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor;
-import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
import com.android.ide.eclipse.editors.resources.manager.ResourceFolder;
import com.android.ide.eclipse.editors.resources.manager.ResourceManager;
+import com.android.ide.eclipse.editors.ui.tree.UiActions;
import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IProgressMonitor;
@@ -47,12 +50,10 @@
*/
public class LayoutEditor extends AndroidEditor implements IShowEditorInput, IPartListener {
- public static final String ID = "com.android.ide.eclipse.editors.layout.LayoutEditor"; //$NON-NLS-1$
+ public static final String ID = AndroidConstants.EDITORS_NAMESPACE + ".layout.LayoutEditor"; //$NON-NLS-1$
/** Root node of the UI element hierarchy */
private UiDocumentNode mUiRootNode;
- /** Listener to update the root node if the resource framework changes */
- private Runnable mResourceRefreshListener;
private GraphicalLayoutEditor mGraphicalEditor;
private int mGraphicalEditorIndex;
@@ -61,13 +62,13 @@
/** Custom implementation of {@link IPropertySheetPage} for this editor */
private UiPropertySheetPage mPropertyPage;
+ private UiEditorActions mUiEditorActions;
/**
* Creates the form editor for resources XML files.
*/
public LayoutEditor() {
super();
- initUiRootNode();
}
/**
@@ -82,10 +83,6 @@
@Override
public void dispose() {
- if (mResourceRefreshListener != null) {
- EditorsPlugin.getDefault().removeResourceChangedListener(mResourceRefreshListener);
- mResourceRefreshListener = null;
- }
getSite().getPage().removePartListener(this);
super.dispose();
@@ -155,7 +152,7 @@
getSite().getPage().addPartListener(this);
}
} catch (PartInitException e) {
- EditorsPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
+ AdtPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
}
}
@@ -222,6 +219,9 @@
*/
@Override
protected void xmlModelChanged(Document xml_doc) {
+ // init the ui root on demand
+ initUiRootNode(false /*force*/);
+
mUiRootNode.loadFromXmlNode(xml_doc);
// update the model first, since it is used by the viewers.
@@ -293,7 +293,11 @@
}
public void partDeactivated(IWorkbenchPart part) {
- // pass
+ if (part == this) {
+ if (mGraphicalEditor != null && getActivePage() == mGraphicalEditorIndex) {
+ mGraphicalEditor.deactivated();
+ }
+ }
}
public void partOpened(IWorkbenchPart part) {
@@ -301,6 +305,32 @@
EclipseUiHelper.showView(EclipseUiHelper.PROPERTY_SHEET_VIEW_ID, false /* activate */);
}
+ public class UiEditorActions extends UiActions {
+
+ @Override
+ protected UiDocumentNode getRootNode() {
+ return mUiRootNode;
+ }
+
+ // Select the new item
+ @Override
+ protected void selectUiNode(UiElementNode uiNodeToSelect) {
+ mGraphicalEditor.selectModel(uiNodeToSelect);
+ }
+
+ @Override
+ public void commitPendingXmlChanges() {
+ // Pass. There is nothing to commit before the XML is changed here.
+ }
+ }
+
+ public UiEditorActions getUiEditorActions() {
+ if (mUiEditorActions == null) {
+ mUiEditorActions = new UiEditorActions();
+ }
+ return mUiEditorActions;
+ }
+
// ---- Local Methods ----
/**
@@ -321,38 +351,50 @@
return false;
}
- /**
- * Creates the initial UI Root Node, including the known mandatory elements.
- */
- private void initUiRootNode() {
+ @Override
+ protected void initUiRootNode(boolean force) {
// The root UI node is always created, even if there's no corresponding XML node.
- if (mUiRootNode == null) {
- DocumentDescriptor desc = LayoutDescriptors.getInstance().getDescriptor();
+ if (mUiRootNode == null || force) {
+ // get the target data from the opened file (and its project)
+ AndroidTargetData data = getTargetData();
+
+ Document doc = null;
+ if (mUiRootNode != null) {
+ doc = mUiRootNode.getXmlDocument();
+ }
+
+ DocumentDescriptor desc;
+ if (data == null) {
+ desc = new DocumentDescriptor("temp", null /*children*/);
+ } else {
+ desc = data.getLayoutDescriptors().getDescriptor();
+ }
+
+ // get the descriptors from the data.
mUiRootNode = (UiDocumentNode) desc.createUiNode();
mUiRootNode.setEditor(this);
- // Add a listener to refresh the root node if the resource framework changes
- // by forcing it to parse its own XML
- mResourceRefreshListener = new Runnable() {
- public void run() {
- commitPages(false /* onSave */);
-
- mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlDocument());
-
- if (mOutline != null) {
- mOutline.reloadModel();
- }
-
- if (mGraphicalEditor != null) {
- mGraphicalEditor.recomputeLayout();
- }
- }
- };
- EditorsPlugin.getDefault().addResourceChangedListener(mResourceRefreshListener);
- mResourceRefreshListener.run();
+ onDescriptorsChanged(doc);
}
}
+ private void onDescriptorsChanged(Document document) {
+ if (document != null) {
+ mUiRootNode.loadFromXmlNode(document);
+ } else {
+ mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlDocument());
+ }
+
+ if (mOutline != null) {
+ mOutline.reloadModel();
+ }
+
+ if (mGraphicalEditor != null) {
+ mGraphicalEditor.reloadEditor();
+ mGraphicalEditor.reloadPalette();
+ mGraphicalEditor.recomputeLayout();
+ }
+ }
/**
* Handles a new input, and update the part name.
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutReloadMonitor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutReloadMonitor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutReloadMonitor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutReloadMonitor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutSourceViewerConfig.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutSourceViewerConfig.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutSourceViewerConfig.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutSourceViewerConfig.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/MatchingStrategy.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/MatchingStrategy.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/MatchingStrategy.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/MatchingStrategy.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java
new file mode 100644
index 0000000..94df28f
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.editors.layout;
+
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+
+import org.eclipse.gef.palette.PaletteDrawer;
+import org.eclipse.gef.palette.PaletteGroup;
+import org.eclipse.gef.palette.PaletteRoot;
+import org.eclipse.gef.palette.PaletteTemplateEntry;
+
+import java.util.List;
+
+/**
+ * Factory that creates the palette for the {@link GraphicalLayoutEditor}.
+ */
+public class PaletteFactory {
+
+ /** Static factory, nothing to instantiate here. */
+ private PaletteFactory() {
+ }
+
+ public static PaletteRoot createPaletteRoot(PaletteRoot currentPalette,
+ AndroidTargetData targetData) {
+
+ if (currentPalette == null) {
+ currentPalette = new PaletteRoot();
+ }
+
+ for (int n = currentPalette.getChildren().size() - 1; n >= 0; n--) {
+ currentPalette.getChildren().remove(n);
+ }
+
+ if (targetData != null) {
+ addTools(currentPalette);
+ addViews(currentPalette, "Layouts",
+ targetData.getLayoutDescriptors().getLayoutDescriptors());
+ addViews(currentPalette, "Views",
+ targetData.getLayoutDescriptors().getViewDescriptors());
+ }
+
+ return currentPalette;
+ }
+
+ private static void addTools(PaletteRoot paletteRoot) {
+ PaletteGroup group = new PaletteGroup("Tools");
+
+ // Default tools: selection.
+ // Do not use the MarqueeToolEntry since we don't support multiple selection.
+ /* -- Do not put the selection tool. It's the unique tool so it looks useless.
+ Leave this piece of code here in case we want it back later.
+ PanningSelectionToolEntry entry = new PanningSelectionToolEntry();
+ group.add(entry);
+ paletteRoot.setDefaultEntry(entry);
+ */
+
+ paletteRoot.add(group);
+ }
+
+ private static void addViews(PaletteRoot paletteRoot, String groupName,
+ List<ElementDescriptor> descriptors) {
+ PaletteDrawer group = new PaletteDrawer(groupName);
+
+ for (ElementDescriptor desc : descriptors) {
+ PaletteTemplateEntry entry = new PaletteTemplateEntry(
+ desc.getUiName(), // label
+ desc.getTooltip(), // short description
+ desc, // template
+ desc.getImageDescriptor(), // small icon
+ desc.getImageDescriptor() // large icon
+ );
+
+ group.add(entry);
+ }
+
+ paletteRoot.add(group);
+ }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java
similarity index 88%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java
index d91ecbc..81fd2ed 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java
@@ -16,6 +16,7 @@
package com.android.ide.eclipse.editors.layout;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestHelper;
import com.android.ide.eclipse.editors.resources.manager.ProjectClassLoader;
@@ -65,12 +66,17 @@
// load the class.
ProjectClassLoader loader = new ProjectClassLoader(mParentClassLoader, mProject);
- clazz = loader.loadClass(className);
-
- if (clazz != null) {
- mUsed = true;
- mLoadedClasses.put(className, clazz);
- return instantiateClass(clazz, constructorSignature, constructorParameters);
+ try {
+ clazz = loader.loadClass(className);
+
+ if (clazz != null) {
+ mUsed = true;
+ mLoadedClasses.put(className, clazz);
+ return instantiateClass(clazz, constructorSignature, constructorParameters);
+ }
+ } catch (Error e) {
+ // Log this error with the class name we're trying to load and abort.
+ AdtPlugin.log(e, "ProjectCallback.loadView failed to find class %1$s", className); //$NON-NLS-1$
}
return null;
@@ -142,7 +148,7 @@
* @param clazz the class to instantiate
* @param constructorSignature the signature of the constructor to use
* @param constructorParameters the parameters to use in the constructor.
- * @return
+ * @return A new class object, created using a specific constructor and parameters.
* @throws Exception
*/
@SuppressWarnings("unchecked")
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java
similarity index 79%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java
index 05f8370..3e0f5d8 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java
@@ -60,7 +60,10 @@
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IActionBars;
+import java.util.ArrayList;
+import java.util.Iterator;
import java.util.LinkedList;
+import java.util.List;
/**
* Implementation of the {@link ContentOutlinePage} to display {@link UiElementNode}.
@@ -84,7 +87,8 @@
mAddAction = new Action("Add...") {
@Override
public void run() {
- UiElementNode node = getModelSelection();
+ List<UiElementNode> nodes = getModelSelections();
+ UiElementNode node = nodes != null && nodes.size() > 0 ? nodes.get(0) : null;
mUiActions.doAdd(node, viewer.getControl().getShell());
}
@@ -95,9 +99,9 @@
mDeleteAction = new Action("Remove...") {
@Override
public void run() {
- UiElementNode node = getModelSelection();
+ List<UiElementNode> nodes = getModelSelections();
- mUiActions.doRemove(node, viewer.getControl().getShell());
+ mUiActions.doRemove(nodes, viewer.getControl().getShell());
}
};
mDeleteAction.setToolTipText("Removes an existing selected element.");
@@ -106,9 +110,9 @@
mUpAction = new Action("Up") {
@Override
public void run() {
- UiElementNode node = getModelSelection();
+ List<UiElementNode> nodes = getModelSelections();
- mUiActions.doUp(node);
+ mUiActions.doUp(nodes);
}
};
mUpAction.setToolTipText("Moves the selected element up");
@@ -117,9 +121,9 @@
mDownAction = new Action("Down") {
@Override
public void run() {
- UiElementNode node = getModelSelection();
+ List<UiElementNode> nodes = getModelSelections();
- mUiActions.doDown(node);
+ mUiActions.doDown(nodes);
}
};
mDownAction.setToolTipText("Moves the selected element down");
@@ -250,7 +254,7 @@
* the necessary actions.
*/
public void menuAboutToShow(IMenuManager manager) {
- UiElementNode selected = getModelSelection();
+ List<UiElementNode> selected = getModelSelections();
if (selected != null) {
doCreateMenuAction(manager, selected);
@@ -269,49 +273,74 @@
* the tree view.
*
* @param manager The context menu manager
- * @param ui_node The UI node selected in the tree. Can be null, in which case the root
+ * @param selected The UI node selected in the tree. Can be null, in which case the root
* is to be modified.
*/
- private void doCreateMenuAction(IMenuManager manager, UiElementNode ui_node) {
- if (ui_node != null && ui_node.getXmlNode() != null) {
- manager.add(new CopyCutAction(mEditor.getLayoutEditor(), mEditor.getClipboard(),
- null, ui_node, true /* cut */));
- manager.add(new CopyCutAction(mEditor.getLayoutEditor(), mEditor.getClipboard(),
- null, ui_node, false /* cut */));
- // Paste is not valid if it would add a second element on a terminal element
- // which parent is a document -- an XML document can only have one child. This
- // means paste is valid if the current UI node can have children or if the parent
- // is not a document.
- UiElementNode ui_root = ui_node.getUiRoot();
- if (ui_root.getDescriptor().hasChildren() ||
- !(ui_root.getUiParent() instanceof UiDocumentNode)) {
- manager.add(new PasteAction(mEditor.getLayoutEditor(), mEditor.getClipboard(),
- ui_node));
+ private void doCreateMenuAction(IMenuManager manager, List<UiElementNode> selected) {
+
+ if (selected != null) {
+ boolean hasXml = false;
+ for (UiElementNode uiNode : selected) {
+ if (uiNode.getXmlNode() != null) {
+ hasXml = true;
+ break;
+ }
}
- manager.add(new Separator());
+
+ if (hasXml) {
+ manager.add(new CopyCutAction(mEditor.getLayoutEditor(), mEditor.getClipboard(),
+ null, selected, true /* cut */));
+ manager.add(new CopyCutAction(mEditor.getLayoutEditor(), mEditor.getClipboard(),
+ null, selected, false /* cut */));
+
+ // Can't paste with more than one element selected (the selection is the target)
+ if (selected.size() <= 1) {
+ // Paste is not valid if it would add a second element on a terminal element
+ // which parent is a document -- an XML document can only have one child. This
+ // means paste is valid if the current UI node can have children or if the parent
+ // is not a document.
+ UiElementNode ui_root = selected.get(0).getUiRoot();
+ if (ui_root.getDescriptor().hasChildren() ||
+ !(ui_root.getUiParent() instanceof UiDocumentNode)) {
+ manager.add(new PasteAction(mEditor.getLayoutEditor(),
+ mEditor.getClipboard(),
+ selected.get(0)));
+ }
+ }
+ manager.add(new Separator());
+ }
}
// Append "add" and "remove" actions. They do the same thing as the add/remove
// buttons on the side.
- manager.add(mAddAction);
- manager.add(mDeleteAction);
+ //
+ // "Add" makes sense only if there's 0 or 1 item selected since the
+ // one selected item becomes the target.
+ if (selected == null || selected.size() <= 1) {
+ manager.add(mAddAction);
+ }
- manager.add(new Separator());
-
- manager.add(mUpAction);
- manager.add(mDownAction);
-
- manager.add(new Separator());
-
- Action propertiesAction = new Action("Properties") {
- @Override
- public void run() {
- EclipseUiHelper.showView(EclipseUiHelper.PROPERTY_SHEET_VIEW_ID,
- true /* activate */);
- }
- };
- propertiesAction.setToolTipText("Displays properties of the selected element.");
- manager.add(propertiesAction);
+ if (selected != null) {
+ manager.add(mDeleteAction);
+ manager.add(new Separator());
+
+ manager.add(mUpAction);
+ manager.add(mDownAction);
+ }
+
+ if (selected != null && selected.size() == 1) {
+ manager.add(new Separator());
+
+ Action propertiesAction = new Action("Properties") {
+ @Override
+ public void run() {
+ EclipseUiHelper.showView(EclipseUiHelper.PROPERTY_SHEET_VIEW_ID,
+ true /* activate */);
+ }
+ };
+ propertiesAction.setToolTipText("Displays properties of the selected element.");
+ manager.add(propertiesAction);
+ }
}
/**
@@ -321,18 +350,20 @@
*/
public void reloadModel() {
// Attemps to preserve the UiNode selection, if any
- UiElementNode uiNode = null;
+ List<UiElementNode> uiNodes = null;
try {
// get current selection using the model rather than the edit part as
// reloading the content may change the actual edit part.
- uiNode = getModelSelection();
+ uiNodes = getModelSelections();
// perform the update
getViewer().setContents(mEditor.getModel());
} finally {
// restore selection
- setModelSelection(uiNode);
+ if (uiNodes != null) {
+ setModelSelection(uiNodes.get(0));
+ }
}
}
@@ -344,17 +375,24 @@
* When there is no actual selection, this might still return the root node,
* which is of type {@link UiDocumentTreeEditPart}.
*/
- private UiElementTreeEditPart getViewerSelection() {
+ @SuppressWarnings("unchecked")
+ private List<UiElementTreeEditPart> getViewerSelections() {
ISelection selection = getSelection();
if (selection instanceof StructuredSelection) {
StructuredSelection structuredSelection = (StructuredSelection)selection;
- if (structuredSelection.size() == 1) {
- Object selectedObj = structuredSelection.getFirstElement();
+ if (structuredSelection.size() > 0) {
+ ArrayList<UiElementTreeEditPart> selected = new ArrayList<UiElementTreeEditPart>();
- if (selectedObj instanceof UiElementTreeEditPart) {
- return (UiElementTreeEditPart) selectedObj;
+ for (Iterator it = structuredSelection.iterator(); it.hasNext(); ) {
+ Object selectedObj = it.next();
+
+ if (selectedObj instanceof UiElementTreeEditPart) {
+ selected.add((UiElementTreeEditPart) selectedObj);
+ }
}
+
+ return selected.size() > 0 ? selected : null;
}
}
@@ -368,13 +406,22 @@
* Returns null if there is no selection or if the implicit root is "selected"
* (which actually represents the lack of a real element selection.)
*/
- private UiElementNode getModelSelection() {
+ private List<UiElementNode> getModelSelections() {
- UiElementTreeEditPart part = getViewerSelection();
+ List<UiElementTreeEditPart> parts = getViewerSelections();
- if (part instanceof UiViewTreeEditPart || part instanceof UiLayoutTreeEditPart) {
- return (UiElementNode) part.getModel();
+ if (parts != null) {
+ ArrayList<UiElementNode> selected = new ArrayList<UiElementNode>();
+
+ for (UiElementTreeEditPart part : parts) {
+ if (part instanceof UiViewTreeEditPart || part instanceof UiLayoutTreeEditPart) {
+ selected.add((UiElementNode) part.getModel());
+ }
+ }
+
+ return selected.size() > 0 ? selected : null;
}
+
return null;
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java
new file mode 100644
index 0000000..b0e6fdb
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.editors.layout;
+
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+import com.android.layoutlib.api.IXmlPullParser;
+
+import org.w3c.dom.Node;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * {@link IXmlPullParser} implementation on top of {@link UiElementNode}.
+ * <p/>It's designed to work on layout files, and will most likely not work on other resource
+ * files.
+ */
+public final class UiElementPullParser extends BasePullParser {
+
+ private final ArrayList<UiElementNode> mNodeStack = new ArrayList<UiElementNode>();
+ private UiElementNode mRoot;
+
+ public UiElementPullParser(UiElementNode top) {
+ super();
+ mRoot = top;
+ push(mRoot);
+ }
+
+ private UiElementNode getCurrentNode() {
+ if (mNodeStack.size() > 0) {
+ return mNodeStack.get(mNodeStack.size()-1);
+ }
+
+ return null;
+ }
+
+ private Node getAttribute(int i) {
+ if (mParsingState != START_TAG) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ // get the current uiNode
+ UiElementNode uiNode = getCurrentNode();
+
+ // get its xml node
+ Node xmlNode = uiNode.getXmlNode();
+
+ if (xmlNode != null) {
+ return xmlNode.getAttributes().item(i);
+ }
+
+ return null;
+ }
+
+ private void push(UiElementNode node) {
+ mNodeStack.add(node);
+ }
+
+ private UiElementNode pop() {
+ return mNodeStack.remove(mNodeStack.size()-1);
+ }
+
+ // ------------- IXmlPullParser --------
+
+ /**
+ * {@inheritDoc}
+ *
+ * This implementation returns the underlying DOM node.
+ */
+ public Object getViewKey() {
+ return getCurrentNode();
+ }
+
+ // ------------- XmlPullParser --------
+
+ public String getPositionDescription() {
+ return "XML DOM element depth:" + mNodeStack.size();
+ }
+
+ public int getAttributeCount() {
+ UiElementNode node = getCurrentNode();
+ if (node != null) {
+ return node.getUiAttributes().size();
+ }
+
+ return 0;
+ }
+
+ public String getAttributeName(int i) {
+ Node attribute = getAttribute(i);
+ if (attribute != null) {
+ return attribute.getLocalName();
+ }
+
+ return null;
+ }
+
+ public String getAttributeNamespace(int i) {
+ Node attribute = getAttribute(i);
+ if (attribute != null) {
+ return attribute.getNamespaceURI();
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ public String getAttributePrefix(int i) {
+ Node attribute = getAttribute(i);
+ if (attribute != null) {
+ return attribute.getPrefix();
+ }
+ return null;
+ }
+
+ public String getAttributeValue(int i) {
+ Node attribute = getAttribute(i);
+ if (attribute != null) {
+ return attribute.getNodeValue();
+ }
+
+ return null;
+ }
+
+ public String getAttributeValue(String namespace, String localName) {
+ // get the current uiNode
+ UiElementNode uiNode = getCurrentNode();
+
+ // get its xml node
+ Node xmlNode = uiNode.getXmlNode();
+
+ if (xmlNode != null) {
+ Node attribute = xmlNode.getAttributes().getNamedItemNS(namespace, localName);
+ if (attribute != null) {
+ return attribute.getNodeValue();
+ }
+ }
+
+ return null;
+ }
+
+ public int getDepth() {
+ return mNodeStack.size();
+ }
+
+ public String getName() {
+ if (mParsingState == START_TAG || mParsingState == END_TAG) {
+ return getCurrentNode().getDescriptor().getXmlLocalName();
+ }
+
+ return null;
+ }
+
+ public String getNamespace() {
+ if (mParsingState == START_TAG || mParsingState == END_TAG) {
+ return getCurrentNode().getDescriptor().getNamespace();
+ }
+
+ return null;
+ }
+
+ public String getPrefix() {
+ if (mParsingState == START_TAG || mParsingState == END_TAG) {
+ // FIXME will NEVER work
+ if (getCurrentNode().getDescriptor().getXmlLocalName().startsWith("android:")) { //$NON-NLS-1$
+ return "android"; //$NON-NLS-1$
+ }
+ }
+
+ return null;
+ }
+
+ public boolean isEmptyElementTag() throws XmlPullParserException {
+ if (mParsingState == START_TAG) {
+ return getCurrentNode().getUiChildren().size() == 0;
+ }
+
+ throw new XmlPullParserException("Call to isEmptyElementTag while not in START_TAG",
+ this, null);
+ }
+
+ @Override
+ public void onNextFromStartDocument() {
+ onNextFromStartTag();
+ }
+
+ @Override
+ public void onNextFromStartTag() {
+ // get the current node, and look for text or children (children first)
+ UiElementNode node = getCurrentNode();
+ List<UiElementNode> children = node.getUiChildren();
+ if (children.size() > 0) {
+ // move to the new child, and don't change the state.
+ push(children.get(0));
+
+ // in case the current state is CURRENT_DOC, we set the proper state.
+ mParsingState = START_TAG;
+ } else {
+ if (mParsingState == START_DOCUMENT) {
+ // this handles the case where there's no node.
+ mParsingState = END_DOCUMENT;
+ } else {
+ mParsingState = END_TAG;
+ }
+ }
+ }
+
+ @Override
+ public void onNextFromEndTag() {
+ // look for a sibling. if no sibling, go back to the parent
+ UiElementNode node = getCurrentNode();
+ node = node.getUiNextSibling();
+ if (node != null) {
+ // to go to the sibling, we need to remove the current node,
+ pop();
+ // and add its sibling.
+ push(node);
+ mParsingState = START_TAG;
+ } else {
+ // move back to the parent
+ pop();
+
+ // we have only one element left (mRoot), then we're done with the document.
+ if (mNodeStack.size() == 1) {
+ mParsingState = END_DOCUMENT;
+ } else {
+ mParsingState = END_TAG;
+ }
+ }
+ }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiPropertySheetPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiPropertySheetPage.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiPropertySheetPage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiPropertySheetPage.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/WidgetPullParser.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/WidgetPullParser.java
new file mode 100644
index 0000000..75d10ed
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/WidgetPullParser.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.editors.layout;
+
+import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor;
+import com.android.layoutlib.api.IXmlPullParser;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+/**
+ * {@link IXmlPullParser} implementation to render android widget bitmap.
+ * <p/>The parser emulates a layout that contains just one widget, described by the
+ * {@link ViewElementDescriptor} passed in the constructor.
+ */
+public class WidgetPullParser extends BasePullParser {
+
+ private final ViewElementDescriptor mDescriptor;
+ private String[][] mAttributes = new String[][] {
+ { "text", null },
+ { "layout_width", "wrap_content" },
+ { "layout_height", "wrap_content" },
+ };
+
+ public WidgetPullParser(ViewElementDescriptor descriptor) {
+ mDescriptor = descriptor;
+
+ String[] segments = mDescriptor.getCanonicalClassName().split(AndroidConstants.RE_DOT);
+ mAttributes[0][1] = segments[segments.length-1];
+ }
+
+ public Object getViewKey() {
+ // we need a viewKey or the ILayoutResult will not contain any ILayoutViewInfo
+ return mDescriptor;
+ }
+
+ public int getAttributeCount() {
+ return mAttributes.length; // text attribute
+ }
+
+ public String getAttributeName(int index) {
+ if (index < mAttributes.length) {
+ return mAttributes[index][0];
+ }
+
+ return null;
+ }
+
+ public String getAttributeNamespace(int index) {
+ return AndroidConstants.NS_RESOURCES;
+ }
+
+ public String getAttributePrefix(int index) {
+ // pass
+ return null;
+ }
+
+ public String getAttributeValue(int index) {
+ if (index < mAttributes.length) {
+ return mAttributes[index][1];
+ }
+
+ return null;
+ }
+
+ public String getAttributeValue(String ns, String name) {
+ if (AndroidConstants.NS_RESOURCES.equals(ns)) {
+ for (String[] attribute : mAttributes) {
+ if (name.equals(attribute[0])) {
+ return attribute[1];
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public int getDepth() {
+ // pass
+ return 0;
+ }
+
+ public String getName() {
+ return mDescriptor.getXmlLocalName();
+ }
+
+ public String getNamespace() {
+ // pass
+ return null;
+ }
+
+ public String getPositionDescription() {
+ // pass
+ return null;
+ }
+
+ public String getPrefix() {
+ // pass
+ return null;
+ }
+
+ public boolean isEmptyElementTag() throws XmlPullParserException {
+ if (mParsingState == START_TAG) {
+ return true;
+ }
+
+ throw new XmlPullParserException("Call to isEmptyElementTag while not in START_TAG",
+ this, null);
+ }
+
+ @Override
+ public void onNextFromStartDocument() {
+ // just go to start_tag
+ mParsingState = START_TAG;
+ }
+
+ @Override
+ public void onNextFromStartTag() {
+ // since we have no children, just go to end_tag
+ mParsingState = END_TAG;
+ }
+
+ @Override
+ public void onNextFromEndTag() {
+ // just one tag. we are done.
+ mParsingState = END_DOCUMENT;
+ }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/CustomViewDescriptorService.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/CustomViewDescriptorService.java
similarity index 92%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/CustomViewDescriptorService.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/CustomViewDescriptorService.java
index c3e9b70..0f388f4 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/CustomViewDescriptorService.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/CustomViewDescriptorService.java
@@ -16,9 +16,12 @@
package com.android.ide.eclipse.editors.layout.descriptors;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.resources.ViewClassInfo;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.NullProgressMonitor;
@@ -192,15 +195,24 @@
private ViewElementDescriptor getDescriptor(IType type, IProject project,
ITypeHierarchy typeHierarchy) {
// check if the type is a built-in View class.
- List<ElementDescriptor> builtInList = LayoutDescriptors.getInstance().getViewDescriptors();
-
+ List<ElementDescriptor> builtInList = null;
+
+ Sdk currentSdk = Sdk.getCurrent();
+ IAndroidTarget target = currentSdk.getTarget(project);
+ if (target != null) {
+ AndroidTargetData data = currentSdk.getTargetData(target);
+ builtInList = data.getLayoutDescriptors().getViewDescriptors();
+ }
+
String canonicalName = type.getFullyQualifiedName();
- for (ElementDescriptor desc : builtInList) {
- if (desc instanceof ViewElementDescriptor) {
- ViewElementDescriptor viewDescriptor = (ViewElementDescriptor)desc;
- if (canonicalName.equals(viewDescriptor.getCanonicalClassName())) {
- return viewDescriptor;
+ if (builtInList != null) {
+ for (ElementDescriptor desc : builtInList) {
+ if (desc instanceof ViewElementDescriptor) {
+ ViewElementDescriptor viewDescriptor = (ViewElementDescriptor)desc;
+ if (canonicalName.equals(viewDescriptor.getCanonicalClassName())) {
+ return viewDescriptor;
+ }
}
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java
similarity index 91%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java
index 8ad2382..cad9ccf 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java
@@ -24,6 +24,7 @@
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor;
import java.util.ArrayList;
@@ -34,31 +35,26 @@
/**
* Complete description of the layout structure.
*/
-public class LayoutDescriptors {
+public final class LayoutDescriptors implements IDescriptorProvider {
// Public attributes names, attributes descriptors and elements descriptors
public static final String ID_ATTR = "id"; //$NON-NLS-1$
- /** Singleton instance */
- private static LayoutDescriptors sThis;
-
/** The document descriptor. Contains all layouts and views linked together. */
private DocumentDescriptor mDescriptor =
new DocumentDescriptor("layout_doc", null); //$NON-NLS-1$
/** The list of all known ViewLayout descriptors. */
private ArrayList<ElementDescriptor> mLayoutDescriptors = new ArrayList<ElementDescriptor>();
-
+
+ /** Read-Only list of View Descriptors. */
+ private List<ElementDescriptor> mROLayoutDescriptors;
+
/** The list of all known View (not ViewLayout) descriptors. */
private ArrayList<ElementDescriptor> mViewDescriptors = new ArrayList<ElementDescriptor>();
- /** Returns a singleton instance of the {@link LayoutDescriptors}. */
- public static synchronized LayoutDescriptors getInstance() {
- if (sThis == null) {
- sThis = new LayoutDescriptors();
- }
- return sThis;
- }
+ /** Read-Only list of View Descriptors. */
+ private List<ElementDescriptor> mROViewDescriptors;
/** @return the document descriptor. Contains all layouts and views linked together. */
public DocumentDescriptor getDescriptor() {
@@ -67,12 +63,16 @@
/** @return The read-only list of all known ViewLayout descriptors. */
public List<ElementDescriptor> getLayoutDescriptors() {
- return Collections.unmodifiableList(mLayoutDescriptors);
+ return mROLayoutDescriptors;
}
/** @return The read-only list of all known View (not ViewLayout) descriptors. */
public List<ElementDescriptor> getViewDescriptors() {
- return Collections.unmodifiableList(mViewDescriptors);
+ return mROViewDescriptors;
+ }
+
+ public ElementDescriptor[] getRootElementDescriptors() {
+ return mDescriptor.getChildren();
}
/**
@@ -118,6 +118,9 @@
mViewDescriptors = newViews;
mLayoutDescriptors = newLayouts;
mDescriptor.setChildren(newArray);
+
+ mROLayoutDescriptors = Collections.unmodifiableList(mLayoutDescriptors);
+ mROViewDescriptors = Collections.unmodifiableList(mViewDescriptors);
}
/**
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/ViewElementDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/ViewElementDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/ViewElementDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/ViewElementDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/DropFeedback.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/DropFeedback.java
new file mode 100644
index 0000000..6e79d64
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/DropFeedback.java
@@ -0,0 +1,761 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.editors.layout.parts;
+
+import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
+import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.layout.LayoutConstants;
+import com.android.ide.eclipse.editors.layout.LayoutEditor.UiEditorActions;
+import com.android.ide.eclipse.editors.layout.parts.UiLayoutEditPart.HighlightInfo;
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+
+import java.util.HashMap;
+import java.util.Map.Entry;
+
+/**
+ * Utility methods used when dealing with dropping EditPart on the GLE.
+ * <p/>
+ * This class uses some temporary static storage to avoid excessive allocations during
+ * drop operations. It is expected to only be invoked from the main UI thread with no
+ * concurrent access.
+ */
+class DropFeedback {
+
+ private static final int TOP = 0;
+ private static final int LEFT = 1;
+ private static final int BOTTOM = 2;
+ private static final int RIGHT = 3;
+ private static final int MAX_DIR = RIGHT;
+
+ private static final int sOppositeDirection[] = { BOTTOM, RIGHT, TOP, LEFT };
+
+ private static final UiElementEditPart sTempClosests[] = new UiElementEditPart[4];
+ private static final int sTempMinDists[] = new int[4];
+
+
+ /**
+ * Target information computed from a drop on a RelativeLayout.
+ * We need only one instance of this and it is sRelativeInfo.
+ */
+ private static class RelativeInfo {
+ /** The two target parts 0 and 1. They can be null, meaning a border is used.
+ * The direction from part 0 to 1 is always to-the-right or to-the-bottom. */
+ final UiElementEditPart targetParts[] = new UiElementEditPart[2];
+ /** Direction from the anchor part to the drop point. */
+ int direction;
+ /** The index of the "anchor" part, i.e. the closest one selected by the drop.
+ * This can be either 0 or 1. The corresponding part can be null. */
+ int anchorIndex;
+ }
+
+ /** The single RelativeInfo used to compute results from a drop on a RelativeLayout */
+ private static final RelativeInfo sRelativeInfo = new RelativeInfo();
+ /** A temporary array of 2 {@link UiElementEditPart} to avoid allocations. */
+ private static final UiElementEditPart sTempTwoParts[] = new UiElementEditPart[2];
+
+
+ private DropFeedback() {
+ }
+
+
+ //----- Package methods called by users of this helper class -----
+
+
+ /**
+ * This method is used by {@link ElementCreateCommand#execute()} when a new item
+ * needs to be "dropped" in the current XML document. It creates the new item using
+ * the given descriptor as a child of the given parent part.
+ *
+ * @param parentPart The parent part.
+ * @param descriptor The descriptor for the new XML element.
+ * @param where The drop location (in parent coordinates)
+ * @param actions The helper that actually modifies the XML model.
+ */
+ static void addElementToXml(UiElementEditPart parentPart,
+ ElementDescriptor descriptor, Point where,
+ UiEditorActions actions) {
+
+ String layoutXmlName = getXmlLocalName(parentPart);
+ RelativeInfo info = null;
+ UiElementEditPart sibling = null;
+
+ if (LayoutConstants.LINEAR_LAYOUT.equals(layoutXmlName)) {
+ sibling = findLinearTarget(parentPart, where)[1];
+
+ } else if (LayoutConstants.RELATIVE_LAYOUT.equals(layoutXmlName)) {
+ info = findRelativeTarget(parentPart, where, sRelativeInfo);
+ if (info != null) {
+ sibling = info.targetParts[info.anchorIndex];
+ sibling = getNextUiSibling(sibling);
+ }
+ }
+
+ if (actions != null) {
+ UiElementNode uiSibling = sibling != null ? sibling.getUiNode() : null;
+ UiElementNode uiParent = parentPart.getUiNode();
+ UiElementNode uiNode = actions.addElement(uiParent, uiSibling, descriptor,
+ false /*updateLayout*/);
+
+ if (LayoutConstants.ABSOLUTE_LAYOUT.equals(layoutXmlName)) {
+ adjustAbsoluteAttributes(uiNode, where);
+ } else if (LayoutConstants.RELATIVE_LAYOUT.equals(layoutXmlName)) {
+ adustRelativeAttributes(uiNode, info);
+ }
+ }
+ }
+
+ /**
+ * This method is used by {@link UiLayoutEditPart#showDropTarget(Point)} to compute
+ * highlight information when a drop target is moved over a valid drop area.
+ * <p/>
+ * Since there are no "out" parameters in Java, all the information is returned
+ * via the {@link HighlightInfo} structure passed as parameter.
+ *
+ * @param parentPart The parent part, always a layout.
+ * @param highlightInfo A structure where result is stored to perform highlight.
+ * @param where The target drop point, in parent's coordinates
+ * @return The {@link HighlightInfo} structured passed as a parameter, for convenience.
+ */
+ static HighlightInfo computeDropFeedback(UiLayoutEditPart parentPart,
+ HighlightInfo highlightInfo,
+ Point where) {
+ String layoutType = getXmlLocalName(parentPart);
+
+ if (LayoutConstants.ABSOLUTE_LAYOUT.equals(layoutType)) {
+ highlightInfo.anchorPoint = where;
+
+ } else if (LayoutConstants.LINEAR_LAYOUT.equals(layoutType)) {
+ boolean isVertical = isVertical(parentPart);
+
+ highlightInfo.childParts = findLinearTarget(parentPart, where);
+ computeLinearLine(parentPart, isVertical, highlightInfo);
+
+ } else if (LayoutConstants.RELATIVE_LAYOUT.equals(layoutType)) {
+
+ RelativeInfo info = findRelativeTarget(parentPart, where, sRelativeInfo);
+ if (info != null) {
+ highlightInfo.childParts = sRelativeInfo.targetParts;
+ computeRelativeLine(parentPart, info, highlightInfo);
+ }
+ }
+
+ return highlightInfo;
+ }
+
+
+ //----- Misc utilities -----
+
+ /**
+ * Returns the next UI sibling of this part, i.e. the element which is just after in
+ * the UI/XML order in the same parent. Returns null if there's no such part.
+ * <p/>
+ * Note: by "UI sibling" here we mean the sibling in the UiNode hierarchy. By design the
+ * UiNode model has the <em>exact</em> same order as the XML model. This has nothing to do
+ * with the "user interface" order that you see on the rendered Android layouts (e.g. for
+ * LinearLayout they are the same but for AbsoluteLayout or RelativeLayout the UI/XML model
+ * order can be vastly different from the user interface order.)
+ */
+ private static UiElementEditPart getNextUiSibling(UiElementEditPart part) {
+ if (part != null) {
+ UiElementNode uiNode = part.getUiNode();
+ if (uiNode != null) {
+ uiNode = uiNode.getUiNextSibling();
+ }
+ if (uiNode != null) {
+ for (Object childPart : part.getParent().getChildren()) {
+ if (childPart instanceof UiElementEditPart &&
+ ((UiElementEditPart) childPart).getUiNode() == uiNode) {
+ return (UiElementEditPart) childPart;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the XML local name of the ui node associated with this edit part or null.
+ */
+ private static String getXmlLocalName(UiElementEditPart editPart) {
+ UiElementNode uiNode = editPart.getUiNode();
+ if (uiNode != null) {
+ ElementDescriptor desc = uiNode.getDescriptor();
+ if (desc != null) {
+ return desc.getXmlLocalName();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Adjusts the attributes of a new node dropped in an AbsoluteLayout.
+ *
+ * @param uiNode The new node being dropped.
+ * @param where The drop location (in parent coordinates)
+ */
+ private static void adjustAbsoluteAttributes(final UiElementNode uiNode, final Point where) {
+ if (where == null) {
+ return;
+ }
+ uiNode.getEditor().editXmlModel(new Runnable() {
+ public void run() {
+ uiNode.setAttributeValue(LayoutConstants.ATTR_LAYOUT_X,
+ String.format(LayoutConstants.VALUE_N_DIP, where.x),
+ false /* override */);
+ uiNode.setAttributeValue(LayoutConstants.ATTR_LAYOUT_Y,
+ String.format(LayoutConstants.VALUE_N_DIP, where.y),
+ false /* override */);
+
+ uiNode.commitDirtyAttributesToXml();
+ }
+ });
+ }
+
+ /**
+ * Adjusts the attributes of a new node dropped in a RelativeLayout:
+ * <ul>
+ * <li> anchor part: the one the user selected (or the closest) and to which the new one
+ * will "attach". The anchor part can be null, either because the layout is currently
+ * empty or the user is attaching to an existing empty border.
+ * <li> direction: the direction from the anchor part to the drop point. That's also the
+ * direction from the anchor part to the new part.
+ * <li> the new node; it is created either after the anchor for right or top directions
+ * or before the anchor for left or bottom directions. This means the new part can
+ * reference the id of the anchor part.
+ * </ul>
+ *
+ * Several cases:
+ * <ul>
+ * <li> set: layout_above/below/toLeftOf/toRightOf to point to the anchor.
+ * <li> copy: layout_centerHorizontal for top/bottom directions
+ * <li> copy: layout_centerVertical for left/right directions.
+ * <li> copy: layout_above/below/toLeftOf/toRightOf for the orthogonal direction
+ * (i.e. top/bottom or left/right.)
+ * </ul>
+ *
+ * @param uiNode The new node being dropped.
+ * @param info The context computed by {@link #findRelativeTarget(UiElementEditPart, Point, RelativeInfo)}.
+ */
+ private static void adustRelativeAttributes(final UiElementNode uiNode, RelativeInfo info) {
+ if (uiNode == null || info == null) {
+ return;
+ }
+
+ final UiElementEditPart anchorPart = info.targetParts[info.anchorIndex]; // can be null
+ final int direction = info.direction;
+
+ uiNode.getEditor().editXmlModel(new Runnable() {
+ public void run() {
+ HashMap<String, String> map = new HashMap<String, String>();
+
+ UiElementNode anchorUiNode = anchorPart != null ? anchorPart.getUiNode() : null;
+ String anchorId = anchorUiNode != null
+ ? anchorUiNode.getAttributeValue("id") //$NON-NLS-1$
+ : null;
+
+ if (anchorId == null) {
+ anchorId = DescriptorsUtils.getFreeWidgetId(anchorUiNode);
+ anchorUiNode.setAttributeValue("id", anchorId, true /*override*/); //$NON-NLS-1$
+ }
+
+ if (anchorId != null) {
+ switch(direction) {
+ case TOP:
+ map.put(LayoutConstants.ATTR_LAYOUT_ABOVE, anchorId);
+ break;
+ case BOTTOM:
+ map.put(LayoutConstants.ATTR_LAYOUT_BELOW, anchorId);
+ break;
+ case LEFT:
+ map.put(LayoutConstants.ATTR_LAYOUT_TO_LEFT_OF, anchorId);
+ break;
+ case RIGHT:
+ map.put(LayoutConstants.ATTR_LAYOUT_TO_RIGHT_OF, anchorId);
+ break;
+ }
+
+ switch(direction) {
+ case TOP:
+ case BOTTOM:
+ map.put(LayoutConstants.ATTR_LAYOUT_CENTER_HORIZONTAL,
+ anchorUiNode.getAttributeValue(
+ LayoutConstants.ATTR_LAYOUT_CENTER_HORIZONTAL));
+
+ map.put(LayoutConstants.ATTR_LAYOUT_TO_LEFT_OF,
+ anchorUiNode.getAttributeValue(
+ LayoutConstants.ATTR_LAYOUT_TO_LEFT_OF));
+ map.put(LayoutConstants.ATTR_LAYOUT_TO_RIGHT_OF,
+ anchorUiNode.getAttributeValue(
+ LayoutConstants.ATTR_LAYOUT_TO_RIGHT_OF));
+ break;
+ case LEFT:
+ case RIGHT:
+ map.put(LayoutConstants.ATTR_LAYOUT_CENTER_VERTICAL,
+ anchorUiNode.getAttributeValue(
+ LayoutConstants.ATTR_LAYOUT_CENTER_VERTICAL));
+ map.put(LayoutConstants.ATTR_LAYOUT_ALIGN_BASELINE,
+ anchorUiNode.getAttributeValue(
+ LayoutConstants.ATTR_LAYOUT_ALIGN_BASELINE));
+
+ map.put(LayoutConstants.ATTR_LAYOUT_ABOVE,
+ anchorUiNode.getAttributeValue(LayoutConstants.ATTR_LAYOUT_ABOVE));
+ map.put(LayoutConstants.ATTR_LAYOUT_BELOW,
+ anchorUiNode.getAttributeValue(LayoutConstants.ATTR_LAYOUT_BELOW));
+ break;
+ }
+ } else {
+ // We don't have an anchor node. Assume we're targeting a border and align
+ // to the parent.
+ switch(direction) {
+ case TOP:
+ map.put(LayoutConstants.ATTR_LAYOUT_ALIGN_PARENT_TOP,
+ LayoutConstants.VALUE_TRUE);
+ break;
+ case BOTTOM:
+ map.put(LayoutConstants.ATTR_LAYOUT_ALIGN_PARENT_BOTTOM,
+ LayoutConstants.VALUE_TRUE);
+ break;
+ case LEFT:
+ map.put(LayoutConstants.ATTR_LAYOUT_ALIGN_PARENT_LEFT,
+ LayoutConstants.VALUE_TRUE);
+ break;
+ case RIGHT:
+ map.put(LayoutConstants.ATTR_LAYOUT_ALIGN_PARENT_RIGHT,
+ LayoutConstants.VALUE_TRUE);
+ break;
+ }
+ }
+
+ for (Entry<String, String> entry : map.entrySet()) {
+ uiNode.setAttributeValue(entry.getKey(), entry.getValue(), true /* override */);
+ }
+ uiNode.commitDirtyAttributesToXml();
+ }
+ });
+ }
+
+
+ //----- LinearLayout --------
+
+ /**
+ * For a given parent edit part that MUST represent a LinearLayout, finds the
+ * element before which the location points.
+ * <p/>
+ * This computes the edit part that corresponds to what will be the "next sibling" of the new
+ * element.
+ * <p/>
+ * It returns null if it can't be determined, in which case the element will be added at the
+ * end of the parent child list.
+ *
+ * @return The edit parts that correspond to what will be the "prev" and "next sibling" of the
+ * new element. The previous sibling can be null if adding before the first element.
+ * The next sibling can be null if adding after the last element.
+ */
+ private static UiElementEditPart[] findLinearTarget(UiElementEditPart parent, Point point) {
+ // default orientation is horizontal
+ boolean isVertical = isVertical(parent);
+
+ int target = isVertical ? point.y : point.x;
+
+ UiElementEditPart prev = null;
+ UiElementEditPart next = null;
+
+ for (Object child : parent.getChildren()) {
+ if (child instanceof UiElementEditPart) {
+ UiElementEditPart childPart = (UiElementEditPart) child;
+ Point p = childPart.getBounds().getCenter();
+ int middle = isVertical ? p.y : p.x;
+ if (target < middle) {
+ next = childPart;
+ break;
+ }
+ prev = childPart;
+ }
+ }
+
+ sTempTwoParts[0] = prev;
+ sTempTwoParts[1] = next;
+ return sTempTwoParts;
+ }
+
+ /**
+ * Computes the highlight line between two parts.
+ * <p/>
+ * The two parts are listed in HighlightInfo.childParts[2]. Any of the parts
+ * can be null.
+ * The result is stored in HighlightInfo.
+ * <p/>
+ * Caller must clear the HighlightInfo as appropriate before this call.
+ *
+ * @param parentPart The parent part, always a layout.
+ * @param isVertical True for vertical parts, thus computing an horizontal line.
+ * @param highlightInfo The in-out highlight info.
+ */
+ private static void computeLinearLine(UiLayoutEditPart parentPart,
+ boolean isVertical, HighlightInfo highlightInfo) {
+ Rectangle r = parentPart.getBounds();
+
+ if (isVertical) {
+ Point p = null;
+ UiElementEditPart part = highlightInfo.childParts[0];
+ if (part != null) {
+ p = part.getBounds().getBottom();
+ } else {
+ part = highlightInfo.childParts[1];
+ if (part != null) {
+ p = part.getBounds().getTop();
+ }
+ }
+ if (p != null) {
+ // horizontal line with middle anchor point
+ highlightInfo.tempPoints[0].setLocation(0, p.y);
+ highlightInfo.tempPoints[1].setLocation(r.width, p.y);
+ highlightInfo.linePoints = highlightInfo.tempPoints;
+ highlightInfo.anchorPoint = p.setLocation(r.width / 2, p.y);
+ }
+ } else {
+ Point p = null;
+ UiElementEditPart part = highlightInfo.childParts[0];
+ if (part != null) {
+ p = part.getBounds().getRight();
+ } else {
+ part = highlightInfo.childParts[1];
+ if (part != null) {
+ p = part.getBounds().getLeft();
+ }
+ }
+ if (p != null) {
+ // vertical line with middle anchor point
+ highlightInfo.tempPoints[0].setLocation(p.x, 0);
+ highlightInfo.tempPoints[1].setLocation(p.x, r.height);
+ highlightInfo.linePoints = highlightInfo.tempPoints;
+ highlightInfo.anchorPoint = p.setLocation(p.x, r.height / 2);
+ }
+ }
+ }
+
+ /**
+ * Returns true if the linear layout is marked as vertical.
+ *
+ * @param parent The a layout part that must be a LinearLayout
+ * @return True if the linear layout has a vertical orientation attribute.
+ */
+ private static boolean isVertical(UiElementEditPart parent) {
+ String orientation = parent.getStringAttr("orientation"); //$NON-NLS-1$
+ boolean isVertical = "vertical".equals(orientation) || //$NON-NLS-1$
+ "1".equals(orientation); //$NON-NLS-1$
+ return isVertical;
+ }
+
+
+ //----- RelativeLayout --------
+
+ /**
+ * Finds the "target" relative layout item for the drop operation & feedback.
+ * <p/>
+ * If the drop point is exactly on a current item, simply returns the side the drop will occur
+ * compared to the center of that element. For the actual XML, we'll need to insert *after*
+ * that element to make sure that referenced are defined in the right order.
+ * In that case the result contains two elements, the second one always being on the right or
+ * bottom side of the first one. When insert in XML, we want to insert right before that
+ * second element or at the end of the child list if the second element is null.
+ * <p/>
+ * If the drop point is not exactly on a current element, find the closest in each
+ * direction and align with the two closest of these.
+ *
+ * @return null if we fail to find anything (such as there are currently no items to compare
+ * with); otherwise fills the {@link RelativeInfo} and return it.
+ */
+ private static RelativeInfo findRelativeTarget(UiElementEditPart parent,
+ Point point,
+ RelativeInfo outInfo) {
+
+ for (int i = 0; i < 4; i++) {
+ sTempMinDists[i] = Integer.MAX_VALUE;
+ sTempClosests[i] = null;
+ }
+
+
+ for (Object child : parent.getChildren()) {
+ if (child instanceof UiElementEditPart) {
+ UiElementEditPart childPart = (UiElementEditPart) child;
+ Rectangle r = childPart.getBounds();
+ if (r.contains(point)) {
+
+ float rx = ((float)(point.x - r.x) / (float)r.width ) - 0.5f;
+ float ry = ((float)(point.y - r.y) / (float)r.height) - 0.5f;
+
+ /* TOP
+ * \ /
+ * \ /
+ * L X R
+ * / \
+ * / \
+ * BOT
+ */
+
+ int index = 0;
+ if (Math.abs(rx) >= Math.abs(ry)) {
+ if (rx < 0) {
+ outInfo.direction = LEFT;
+ index = 1;
+ } else {
+ outInfo.direction = RIGHT;
+ }
+ } else {
+ if (ry < 0) {
+ outInfo.direction = TOP;
+ index = 1;
+ } else {
+ outInfo.direction = BOTTOM;
+ }
+ }
+
+ outInfo.anchorIndex = index;
+ outInfo.targetParts[index] = childPart;
+ outInfo.targetParts[1 - index] = findClosestPart(childPart,
+ outInfo.direction);
+
+ return outInfo;
+ }
+
+ computeClosest(point, childPart, sTempClosests, sTempMinDists, TOP);
+ computeClosest(point, childPart, sTempClosests, sTempMinDists, LEFT);
+ computeClosest(point, childPart, sTempClosests, sTempMinDists, BOTTOM);
+ computeClosest(point, childPart, sTempClosests, sTempMinDists, RIGHT);
+ }
+ }
+
+ UiElementEditPart closest = null;
+ int minDist = Integer.MAX_VALUE;
+ int minDir = -1;
+
+ for (int i = 0; i <= MAX_DIR; i++) {
+ if (sTempClosests[i] != null && sTempMinDists[i] < minDist) {
+ closest = sTempClosests[i];
+ minDist = sTempMinDists[i];
+ minDir = i;
+ }
+ }
+
+ if (closest != null) {
+ int index = 0;
+ switch(minDir) {
+ case TOP:
+ case LEFT:
+ index = 0;
+ break;
+ case BOTTOM:
+ case RIGHT:
+ index = 1;
+ break;
+ }
+ outInfo.anchorIndex = index;
+ outInfo.targetParts[index] = closest;
+ outInfo.targetParts[1 - index] = findClosestPart(closest, sOppositeDirection[minDir]);
+ outInfo.direction = sOppositeDirection[minDir];
+ return outInfo;
+ }
+
+ return null;
+ }
+
+ /**
+ * Computes the highlight line for a drop on a RelativeLayout.
+ * <p/>
+ * The line is always placed on the side of the anchor part indicated by the
+ * direction. The direction always point from the anchor part to the drop point.
+ * <p/>
+ * If there's no anchor part, use the other one with a reversed direction.
+ * <p/>
+ * On output, this updates the {@link HighlightInfo}.
+ */
+ private static void computeRelativeLine(UiLayoutEditPart parentPart,
+ RelativeInfo relInfo,
+ HighlightInfo highlightInfo) {
+
+ UiElementEditPart[] parts = relInfo.targetParts;
+ int dir = relInfo.direction;
+ int index = relInfo.anchorIndex;
+ UiElementEditPart part = parts[index];
+
+ if (part == null) {
+ dir = sOppositeDirection[dir];
+ part = parts[1 - index];
+ }
+ if (part == null) {
+ // give up if both parts are null
+ return;
+ }
+
+ Rectangle r = part.getBounds();
+ Point p = null;
+ switch(dir) {
+ case TOP:
+ p = r.getTop();
+ break;
+ case BOTTOM:
+ p = r.getBottom();
+ break;
+ case LEFT:
+ p = r.getLeft();
+ break;
+ case RIGHT:
+ p = r.getRight();
+ break;
+ }
+
+ highlightInfo.anchorPoint = p;
+
+ r = parentPart.getBounds();
+ switch(dir) {
+ case TOP:
+ case BOTTOM:
+ // horizontal line with middle anchor point
+ highlightInfo.tempPoints[0].setLocation(0, p.y);
+ highlightInfo.tempPoints[1].setLocation(r.width, p.y);
+ highlightInfo.linePoints = highlightInfo.tempPoints;
+ highlightInfo.anchorPoint = p;
+ break;
+ case LEFT:
+ case RIGHT:
+ // vertical line with middle anchor point
+ highlightInfo.tempPoints[0].setLocation(p.x, 0);
+ highlightInfo.tempPoints[1].setLocation(p.x, r.height);
+ highlightInfo.linePoints = highlightInfo.tempPoints;
+ highlightInfo.anchorPoint = p;
+ break;
+ }
+ }
+
+ /**
+ * Given a certain reference point (drop point), computes the distance to the given
+ * part in the given direction. For example if direction is top, only accepts parts which
+ * bottom is above the reference point, computes their distance and then updates the
+ * current minimal distances and current closest parts arrays accordingly.
+ */
+ private static void computeClosest(Point refPoint,
+ UiElementEditPart compareToPart,
+ UiElementEditPart[] currClosests,
+ int[] currMinDists,
+ int direction) {
+ Rectangle r = compareToPart.getBounds();
+
+ Point p = null;
+ boolean usable = false;
+
+ switch(direction) {
+ case TOP:
+ p = r.getBottom();
+ usable = p.y <= refPoint.y;
+ break;
+ case BOTTOM:
+ p = r.getTop();
+ usable = p.y >= refPoint.y;
+ break;
+ case LEFT:
+ p = r.getRight();
+ usable = p.x <= refPoint.x;
+ break;
+ case RIGHT:
+ p = r.getLeft();
+ usable = p.x >= refPoint.x;
+ break;
+ }
+
+ if (usable) {
+ int d = p.getDistance2(refPoint);
+ if (d < currMinDists[direction]) {
+ currMinDists[direction] = d;
+ currClosests[direction] = compareToPart;
+ }
+ }
+ }
+
+ /**
+ * Given a reference parts, finds the closest part in the parent in the given direction.
+ * For example if direction is top, finds the closest sibling part which is above the
+ * reference part and non-overlapping (they can touch.)
+ */
+ private static UiElementEditPart findClosestPart(UiElementEditPart referencePart,
+ int direction) {
+ if (referencePart == null || referencePart.getParent() == null) {
+ return null;
+ }
+
+ Rectangle r = referencePart.getBounds();
+ Point ref = null;
+ switch(direction) {
+ case TOP:
+ ref = r.getTop();
+ break;
+ case BOTTOM:
+ ref = r.getBottom();
+ break;
+ case LEFT:
+ ref = r.getLeft();
+ break;
+ case RIGHT:
+ ref = r.getRight();
+ break;
+ }
+
+ int minDist = Integer.MAX_VALUE;
+ UiElementEditPart closestPart = null;
+
+ for (Object childPart : referencePart.getParent().getChildren()) {
+ if (childPart != referencePart && childPart instanceof UiElementEditPart) {
+ r = ((UiElementEditPart) childPart).getBounds();
+ Point p = null;
+ boolean usable = false;
+
+ switch(direction) {
+ case TOP:
+ p = r.getBottom();
+ usable = p.y <= ref.y;
+ break;
+ case BOTTOM:
+ p = r.getTop();
+ usable = p.y >= ref.y;
+ break;
+ case LEFT:
+ p = r.getRight();
+ usable = p.x <= ref.x;
+ break;
+ case RIGHT:
+ p = r.getLeft();
+ usable = p.x >= ref.x;
+ break;
+ }
+
+ if (usable) {
+ int d = p.getDistance2(ref);
+ if (d < minDist) {
+ minDist = d;
+ closestPart = (UiElementEditPart) childPart;
+ }
+ }
+ }
+ }
+
+ return closestPart;
+ }
+
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/ElementCreateCommand.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/ElementCreateCommand.java
new file mode 100644
index 0000000..d36d9f7
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/ElementCreateCommand.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.editors.layout.parts;
+
+import com.android.ide.eclipse.editors.AndroidEditor;
+import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.layout.LayoutEditor;
+import com.android.ide.eclipse.editors.layout.LayoutEditor.UiEditorActions;
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.gef.commands.Command;
+
+/**
+ * A command that knows how to instantiate a new element based on a given {@link ElementDescriptor},
+ * the parent {@link UiElementEditPart} and an optional target location.
+ */
+public class ElementCreateCommand extends Command {
+
+ /** Descriptor of the new element to create */
+ private final ElementDescriptor mDescriptor;
+ /** The edit part that hosts the new edit part */
+ private final UiElementEditPart mParentPart;
+ /** The drop location in parent coordinates */
+ private final Point mTargetPoint;
+
+ /**
+ * Creates a new {@link ElementCreateCommand}.
+ *
+ * @param descriptor Descriptor of the new element to create
+ * @param targetPart The edit part that hosts the new edit part
+ * @param targetPoint The drop location in parent coordinates
+ */
+ public ElementCreateCommand(ElementDescriptor descriptor,
+ UiElementEditPart targetPart, Point targetPoint) {
+ mDescriptor = descriptor;
+ mParentPart = targetPart;
+ mTargetPoint = targetPoint;
+ }
+
+ // --- Methods inherited from Command ---
+
+ @Override
+ public boolean canExecute() {
+ return mDescriptor != null &&
+ mParentPart != null &&
+ mParentPart.getUiNode() != null &&
+ mParentPart.getUiNode().getEditor() instanceof LayoutEditor;
+ }
+
+ @Override
+ public void execute() {
+ super.execute();
+ UiElementNode uiParent = mParentPart.getUiNode();
+ if (uiParent != null) {
+ final AndroidEditor editor = uiParent.getEditor();
+ if (editor instanceof LayoutEditor) {
+ ((LayoutEditor) editor).wrapUndoRecording(
+ String.format("Create %1$s", mDescriptor.getXmlLocalName()),
+ new Runnable() {
+ public void run() {
+ UiEditorActions actions = ((LayoutEditor) editor).getUiEditorActions();
+ if (actions != null) {
+ DropFeedback.addElementToXml(mParentPart, mDescriptor, mTargetPoint,
+ actions);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ @Override
+ public void redo() {
+ throw new UnsupportedOperationException("redo not supported by this command"); //$NON-NLS-1$
+ }
+
+ @Override
+ public void undo() {
+ throw new UnsupportedOperationException("undo not supported by this command"); //$NON-NLS-1$
+ }
+
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/ElementFigure.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/ElementFigure.java
new file mode 100644
index 0000000..f863037
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/ElementFigure.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.editors.layout.parts;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.Figure;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.swt.SWT;
+
+
+/**
+ * The figure used to draw basic elements.
+ * <p/>
+ * The figure is totally empty and transparent except for the selection border.
+ */
+class ElementFigure extends Figure {
+
+ private boolean mIsSelected;
+ private Rectangle mInnerBounds;
+
+ public ElementFigure() {
+ setOpaque(false);
+ }
+
+ public void setSelected(boolean isSelected) {
+ if (isSelected != mIsSelected) {
+ mIsSelected = isSelected;
+ repaint();
+ }
+ }
+
+ @Override
+ public void setBounds(Rectangle rect) {
+ super.setBounds(rect);
+
+ mInnerBounds = getBounds().getCopy();
+ if (mInnerBounds.width > 0) {
+ mInnerBounds.width--;
+ }
+ if (mInnerBounds.height > 0) {
+ mInnerBounds.height--;
+ }
+ }
+
+ public Rectangle getInnerBounds() {
+ return mInnerBounds;
+ }
+
+ @Override
+ protected void paintBorder(Graphics graphics) {
+ super.paintBorder(graphics);
+
+ if (mIsSelected) {
+ graphics.setLineWidth(1);
+ graphics.setLineStyle(SWT.LINE_SOLID);
+ graphics.setForegroundColor(ColorConstants.red);
+ graphics.drawRectangle(getInnerBounds());
+ }
+ }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/LayoutFigure.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/LayoutFigure.java
new file mode 100644
index 0000000..55ed39b
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/LayoutFigure.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.editors.layout.parts;
+
+import com.android.ide.eclipse.editors.layout.parts.UiLayoutEditPart.HighlightInfo;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.Figure;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.swt.SWT;
+
+/**
+ * The figure used to draw the feedback on a layout.
+ * <p/>
+ * By default the figure is transparent and empty.
+ * The base {@link ElementFigure} knows how to draw the selection border.
+ * This figure knows how to draw the drop feedback.
+ */
+class LayoutFigure extends ElementFigure {
+
+ private HighlightInfo mHighlightInfo;
+
+ public LayoutFigure() {
+ super();
+ }
+
+ public void setHighlighInfo(HighlightInfo highlightInfo) {
+ mHighlightInfo = highlightInfo;
+ repaint();
+ }
+
+ /**
+ * Paints the "border" for this figure.
+ * <p/>
+ * The parent {@link Figure#paint(Graphics)} calls {@link #paintFigure(Graphics)} then
+ * {@link #paintClientArea(Graphics)} then {@link #paintBorder(Graphics)}. Here we thus
+ * draw the actual highlight border but also the highlight anchor lines and points so that
+ * we can make sure they are all drawn on top of the border.
+ * <p/>
+ * Note: This method doesn't really need to restore its graphic state. The parent
+ * Figure will do it for us.
+ * <p/>
+ *
+ * @param graphics The Graphics object used for painting
+ */
+ @Override
+ protected void paintBorder(Graphics graphics) {
+ super.paintBorder(graphics);
+
+ if (mHighlightInfo == null) {
+ return;
+ }
+
+ // Draw the border. We want other highlighting to be drawn on top of the border.
+ if (mHighlightInfo.drawDropBorder) {
+ graphics.setLineWidth(3);
+ graphics.setLineStyle(SWT.LINE_SOLID);
+ graphics.setForegroundColor(ColorConstants.green);
+ graphics.drawRectangle(getInnerBounds().getCopy().shrink(1, 1));
+ }
+
+ Rectangle bounds = getBounds();
+ int bx = bounds.x;
+ int by = bounds.y;
+ int w = bounds.width;
+ int h = bounds.height;
+
+ // Draw frames of target child parts, if any
+ if (mHighlightInfo.childParts != null) {
+ graphics.setLineWidth(2);
+ graphics.setLineStyle(SWT.LINE_DOT);
+ graphics.setForegroundColor(ColorConstants.lightBlue);
+ for (UiElementEditPart part : mHighlightInfo.childParts) {
+ if (part != null) {
+ graphics.drawRectangle(part.getBounds().getCopy().translate(bx, by));
+ }
+ }
+ }
+
+ // Draw the target line, if any
+ if (mHighlightInfo.linePoints != null) {
+ int x1 = mHighlightInfo.linePoints[0].x;
+ int y1 = mHighlightInfo.linePoints[0].y;
+ int x2 = mHighlightInfo.linePoints[1].x;
+ int y2 = mHighlightInfo.linePoints[1].y;
+
+ // if the line is right to the edge, draw it one pixel more inside so that the
+ // full 2-pixel width be visible.
+ if (x1 <= 0) x1++;
+ if (x2 <= 0) x2++;
+ if (y1 <= 0) y1++;
+ if (y2 <= 0) y2++;
+
+ if (x1 >= w - 1) x1--;
+ if (x2 >= w - 1) x2--;
+ if (y1 >= h - 1) y1--;
+ if (y2 >= h - 1) y2--;
+
+ x1 += bx;
+ x2 += bx;
+ y1 += by;
+ y2 += by;
+
+ graphics.setLineWidth(2);
+ graphics.setLineStyle(SWT.LINE_DASH);
+ graphics.setLineCap(SWT.CAP_ROUND);
+ graphics.setForegroundColor(ColorConstants.orange);
+ graphics.drawLine(x1, y1, x2, y2);
+ }
+
+ // Draw the anchor point, if any
+ if (mHighlightInfo.anchorPoint != null) {
+ int x = mHighlightInfo.anchorPoint.x;
+ int y = mHighlightInfo.anchorPoint.y;
+
+ // If the point is right on the edge, draw it one pixel inside so that it
+ // matches the highlight line. It makes it slightly more visible that way.
+ if (x <= 0) x++;
+ if (y <= 0) y++;
+ if (x >= w - 1) x--;
+ if (y >= h - 1) y--;
+ x += bx;
+ y += by;
+
+ graphics.setLineWidth(2);
+ graphics.setLineStyle(SWT.LINE_SOLID);
+ graphics.setLineCap(SWT.CAP_ROUND);
+ graphics.setForegroundColor(ColorConstants.orange);
+ graphics.drawLine(x-5, y-5, x+5, y+5);
+ graphics.drawLine(x-5, y+5, x+5, y-5);
+ // 7 * cos(45) == 5 so we use 8 for the circle radius (it looks slightly better than 7)
+ graphics.setLineWidth(1);
+ graphics.drawOval(x-8, y-8, 16, 16);
+ }
+ }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentEditPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentEditPart.java
similarity index 66%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentEditPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentEditPart.java
index 53a87f5..2f7636d 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentEditPart.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentEditPart.java
@@ -27,7 +27,14 @@
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.geometry.Insets;
+import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.RequestConstants;
+import org.eclipse.gef.editpolicies.RootComponentEditPolicy;
+import org.eclipse.gef.requests.DropRequest;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
@@ -149,4 +156,57 @@
protected void showSelection() {
// no selection at this level.
}
+
+ @Override
+ protected void createEditPolicies() {
+ super.createEditPolicies();
+
+ // This policy indicates this a root component that cannot be removed
+ installEditPolicy(EditPolicy.COMPONENT_ROLE, new RootComponentEditPolicy());
+
+ installLayoutEditPolicy(this);
+ }
+
+ /**
+ * Returns the EditPart that should be used as the target for the specified Request.
+ * For instance this is called during drag'n'drop with a CreateRequest.
+ * <p/>
+ * For the root document, we want the first child edit part to the be the target
+ * since an XML document can have only one root element.
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public EditPart getTargetEditPart(Request request) {
+ if (request != null && request.getType() == RequestConstants.REQ_CREATE) {
+ // We refuse the drop if it's not in the bounds of the document.
+ if (request instanceof DropRequest) {
+ Point where = ((DropRequest) request).getLocation().getCopy();
+ UiElementNode uiNode = getUiNode();
+ if (uiNode instanceof UiDocumentNode) {
+ // Take the bounds of the background image as the valid drop zone
+ Object editData = uiNode.getEditData();
+ if (editData instanceof BufferedImage) {
+ BufferedImage image = (BufferedImage)editData;
+ int w = image.getWidth();
+ int h = image.getHeight();
+ if (where.x > w || where.y > h) {
+ return null;
+ }
+ }
+
+ }
+ }
+
+ // For the root document, we want the first child edit part to the be the target
+ // since an XML document can have only one root element.
+ if (getChildren().size() > 0) {
+ Object o = getChildren().get(0);
+ if (o instanceof EditPart) {
+ return ((EditPart) o).getTargetEditPart(request);
+ }
+ }
+ }
+ return super.getTargetEditPart(request);
+ }
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentTreeEditPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentTreeEditPart.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentTreeEditPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentTreeEditPart.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java
new file mode 100644
index 0000000..d873005
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.editors.layout.parts;
+
+import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener;
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.DragTracker;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.RequestConstants;
+import org.eclipse.gef.commands.Command;
+import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
+import org.eclipse.gef.editpolicies.LayoutEditPolicy;
+import org.eclipse.gef.editpolicies.SelectionEditPolicy;
+import org.eclipse.gef.requests.CreateRequest;
+import org.eclipse.gef.requests.DropRequest;
+import org.eclipse.gef.tools.SelectEditPartTracker;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import java.util.List;
+
+/**
+ * An {@link EditPart} for a {@link UiElementNode}.
+ */
+public abstract class UiElementEditPart extends AbstractGraphicalEditPart
+ implements IUiUpdateListener {
+
+ public UiElementEditPart(UiElementNode uiElementNode) {
+ setModel(uiElementNode);
+ }
+
+ //-------------------------
+ // Derived classes must define these
+
+ abstract protected void hideSelection();
+ abstract protected void showSelection();
+
+ //-------------------------
+ // Base class overrides
+
+ @Override
+ public DragTracker getDragTracker(Request request) {
+ return new SelectEditPartTracker(this);
+ }
+
+ @Override
+ protected void createEditPolicies() {
+ /*
+ * This is no longer needed, as a selection edit policy is set by the parent layout.
+ * Leave this code commented out right now, I'll want to play with this later.
+ *
+ installEditPolicy(EditPolicy.SELECTION_FEEDBACK_ROLE,
+ new NonResizableSelectionEditPolicy(this));
+ */
+ }
+
+ /* (non-javadoc)
+ * Returns a List containing the children model objects.
+ * Must not return null, instead use the super which returns an empty list.
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ protected List getModelChildren() {
+ return getUiNode().getUiChildren();
+ }
+
+ @Override
+ public void activate() {
+ super.activate();
+ getUiNode().addUpdateListener(this);
+ }
+
+ @Override
+ public void deactivate() {
+ super.deactivate();
+ getUiNode().removeUpdateListener(this);
+ }
+
+ @Override
+ protected void refreshVisuals() {
+ if (getFigure().getParent() != null) {
+ ((GraphicalEditPart) getParent()).setLayoutConstraint(this, getFigure(), getBounds());
+ }
+
+ // update the visuals of the children as well
+ refreshChildrenVisuals();
+ }
+
+ protected void refreshChildrenVisuals() {
+ if (children != null) {
+ for (Object child : children) {
+ if (child instanceof UiElementEditPart) {
+ UiElementEditPart childPart = (UiElementEditPart)child;
+ childPart.refreshVisuals();
+ }
+ }
+ }
+ }
+
+ //-------------------------
+ // IUiUpdateListener implementation
+
+ public void uiElementNodeUpdated(UiElementNode ui_node, UiUpdateState state) {
+ // TODO: optimize by refreshing only when needed
+ switch(state) {
+ case ATTR_UPDATED:
+ refreshVisuals();
+ break;
+ case CHILDREN_CHANGED:
+ refreshChildren();
+
+ // new children list, need to update the layout
+ refreshVisuals();
+ break;
+ case CREATED:
+ refreshVisuals();
+ break;
+ case DELETED:
+ // pass
+ break;
+ }
+ }
+
+ //-------------------------
+ // Local methods
+
+ /** @return The object model casted to an {@link UiElementNode} */
+ public final UiElementNode getUiNode() {
+ return (UiElementNode) getModel();
+ }
+
+ protected final ElementDescriptor getDescriptor() {
+ return getUiNode().getDescriptor();
+ }
+
+ protected final UiElementEditPart getEditPartParent() {
+ EditPart parent = getParent();
+ if (parent instanceof UiElementEditPart) {
+ return (UiElementEditPart)parent;
+ }
+ return null;
+ }
+
+ /**
+ * Returns a given XML attribute.
+ * @param attrName The local name of the attribute.
+ * @return the attribute as a {@link String}, if it exists, or <code>null</code>
+ */
+ protected final String getStringAttr(String attrName) {
+ UiElementNode uiNode = getUiNode();
+ if (uiNode.getXmlNode() != null) {
+ Node xmlNode = uiNode.getXmlNode();
+ if (xmlNode != null) {
+ NamedNodeMap nodeAttributes = xmlNode.getAttributes();
+ if (nodeAttributes != null) {
+ Node attr = nodeAttributes.getNamedItemNS(
+ AndroidConstants.NS_RESOURCES, attrName);
+ if (attr != null) {
+ return attr.getNodeValue();
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ protected final Rectangle getBounds() {
+ UiElementNode model = (UiElementNode)getModel();
+
+ Object editData = model.getEditData();
+
+ if (editData != null) {
+ // assert with fully qualified class name to prevent import changes to another
+ // Rectangle class.
+ assert (editData instanceof org.eclipse.draw2d.geometry.Rectangle);
+
+ return (Rectangle)editData;
+ }
+
+ // return a dummy rect
+ return new Rectangle(0, 0, 0, 0);
+ }
+
+ /**
+ * Returns the EditPart that should be used as the target for the specified Request.
+ * <p/>
+ * For instance this is called during drag'n'drop with a CreateRequest.
+ * <p/>
+ * Reject being a target for elements which descriptor does not allow children.
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public EditPart getTargetEditPart(Request request) {
+ if (request != null && request.getType() == RequestConstants.REQ_CREATE) {
+ // Reject being a target for elements which descriptor does not allow children.
+ if (!getUiNode().getDescriptor().hasChildren()) {
+ return null;
+ }
+ }
+ return super.getTargetEditPart(request);
+ }
+
+ /**
+ * Used by derived classes {@link UiDocumentEditPart} and {@link UiLayoutEditPart}
+ * to accept drag'n'drop of new items from the palette.
+ *
+ * @param layoutEditPart The layout edit part where this policy is installed. It can
+ * be either a {@link UiDocumentEditPart} or a {@link UiLayoutEditPart}.
+ */
+ protected void installLayoutEditPolicy(final UiElementEditPart layoutEditPart) {
+ // This policy indicates how elements can be constrained by the layout.
+ // TODO Right now we use the XY layout policy since our constraints are
+ // handled by the android rendering engine rather than GEF. Tweak as
+ // appropriate.
+ installEditPolicy(EditPolicy.LAYOUT_ROLE, new LayoutEditPolicy() {
+
+ /**
+ * We don't allow layout children to be resized yet.
+ * <p/>
+ * Typical choices would be:
+ * <ul>
+ * <li> ResizableEditPolicy, to allow for selection, move and resize.
+ * <li> NonResizableEditPolicy, to allow for selection, move but not resize.
+ * <li> SelectionEditPolicy to allow for only selection.
+ * </ul>
+ * <p/>
+ * TODO: make this depend on the part layout. For an AbsoluteLayout we should
+ * probably use a NonResizableEditPolicy and SelectionEditPolicy for the rest.
+ * Whether to use ResizableEditPolicy or NonResizableEditPolicy should depend
+ * on the child in an AbsoluteLayout.
+ */
+ @Override
+ protected EditPolicy createChildEditPolicy(EditPart child) {
+ if (child instanceof UiElementEditPart) {
+ return new NonResizableSelectionEditPolicy((UiElementEditPart) child);
+ }
+ return null;
+ }
+
+ @Override
+ protected Command getCreateCommand(CreateRequest request) {
+ // We store the ElementDescriptor in the request.factory.type
+ Object newType = request.getNewObjectType();
+ if (newType instanceof ElementDescriptor) {
+ Point where = request.getLocation().getCopy();
+ Point origin = getLayoutContainer().getClientArea().getLocation();
+ where.translate(origin.getNegated());
+
+ // The host is the EditPart where this policy is installed,
+ // e.g. this UiElementEditPart.
+ EditPart host = getHost();
+ if (host instanceof UiElementEditPart) {
+
+ return new ElementCreateCommand((ElementDescriptor) newType,
+ (UiElementEditPart) host,
+ where);
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ protected Command getMoveChildrenCommand(Request request) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void showLayoutTargetFeedback(Request request) {
+ super.showLayoutTargetFeedback(request);
+
+ // for debugging
+ // System.out.println("target: " + request.toString() + " -- " + layoutEditPart.getUiNode().getBreadcrumbTrailDescription(false));
+
+ if (layoutEditPart instanceof UiLayoutEditPart &&
+ request instanceof DropRequest) {
+ Point where = ((DropRequest) request).getLocation().getCopy();
+ Point origin = getLayoutContainer().getClientArea().getLocation();
+ where.translate(origin.getNegated());
+
+ ((UiLayoutEditPart) layoutEditPart).showDropTarget(where);
+ }
+ }
+
+ @Override
+ protected void eraseLayoutTargetFeedback(Request request) {
+ super.eraseLayoutTargetFeedback(request);
+ if (layoutEditPart instanceof UiLayoutEditPart) {
+ ((UiLayoutEditPart) layoutEditPart).hideDropTarget();
+ }
+ }
+
+ @Override
+ protected IFigure createSizeOnDropFeedback(CreateRequest createRequest) {
+ // TODO understand if this is useful for us or remove
+ return super.createSizeOnDropFeedback(createRequest);
+ }
+
+ });
+ }
+
+ protected static class NonResizableSelectionEditPolicy extends SelectionEditPolicy {
+
+ private final UiElementEditPart mEditPart;
+
+ public NonResizableSelectionEditPolicy(UiElementEditPart editPart) {
+ mEditPart = editPart;
+ }
+
+ @Override
+ protected void hideSelection() {
+ mEditPart.hideSelection();
+ }
+
+ @Override
+ protected void showSelection() {
+ mEditPart.showSelection();
+ }
+ }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPart.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPart.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPartFactory.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPartFactory.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPartFactory.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPartFactory.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementsEditPartFactory.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementsEditPartFactory.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementsEditPartFactory.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementsEditPartFactory.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutEditPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutEditPart.java
new file mode 100644
index 0000000..43a70a5
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutEditPart.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.editors.layout.parts;
+
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.XYLayout;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.commands.Command;
+import org.eclipse.gef.editpolicies.ContainerEditPolicy;
+import org.eclipse.gef.requests.CreateRequest;
+
+/**
+ * Graphical edit part for an {@link UiElementNode} that represents a ViewLayout.
+ * <p/>
+ * It acts as a simple container.
+ */
+public final class UiLayoutEditPart extends UiElementEditPart {
+
+ static class HighlightInfo {
+ public boolean drawDropBorder;
+ public UiElementEditPart[] childParts;
+ public Point anchorPoint;
+ public Point linePoints[];
+
+ public final Point tempPoints[] = new Point[] { new Point(), new Point() };
+
+ public void clear() {
+ drawDropBorder = false;
+ childParts = null;
+ anchorPoint = null;
+ linePoints = null;
+ }
+ }
+
+ private final HighlightInfo mHighlightInfo = new HighlightInfo();
+
+ public UiLayoutEditPart(UiElementNode uiElementNode) {
+ super(uiElementNode);
+ }
+
+ @Override
+ protected void createEditPolicies() {
+ super.createEditPolicies();
+
+ installEditPolicy(EditPolicy.CONTAINER_ROLE, new ContainerEditPolicy() {
+ @Override
+ protected Command getCreateCommand(CreateRequest request) {
+ return null;
+ }
+ });
+
+ installLayoutEditPolicy(this);
+ }
+
+ @Override
+ protected IFigure createFigure() {
+ IFigure f = new LayoutFigure();
+ f.setLayoutManager(new XYLayout());
+ return f;
+ }
+
+ @Override
+ protected void showSelection() {
+ IFigure f = getFigure();
+ if (f instanceof ElementFigure) {
+ ((ElementFigure) f).setSelected(true);
+ }
+ }
+
+ @Override
+ protected void hideSelection() {
+ IFigure f = getFigure();
+ if (f instanceof ElementFigure) {
+ ((ElementFigure) f).setSelected(false);
+ }
+ }
+
+ public void showDropTarget(Point where) {
+ if (where != null) {
+ mHighlightInfo.clear();
+ mHighlightInfo.drawDropBorder = true;
+ DropFeedback.computeDropFeedback(this, mHighlightInfo, where);
+
+ IFigure f = getFigure();
+ if (f instanceof LayoutFigure) {
+ ((LayoutFigure) f).setHighlighInfo(mHighlightInfo);
+ }
+ }
+ }
+
+ public void hideDropTarget() {
+ mHighlightInfo.clear();
+ IFigure f = getFigure();
+ if (f instanceof LayoutFigure) {
+ ((LayoutFigure) f).setHighlighInfo(mHighlightInfo);
+ }
+ }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutTreeEditPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutTreeEditPart.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutTreeEditPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutTreeEditPart.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewEditPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiViewEditPart.java
similarity index 80%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewEditPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiViewEditPart.java
index b427ead..05329f3 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewEditPart.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiViewEditPart.java
@@ -18,10 +18,8 @@
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
-import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.IFigure;
-import org.eclipse.draw2d.Label;
-import org.eclipse.draw2d.LineBorder;
+import org.eclipse.draw2d.XYLayout;
/**
* Graphical edit part for an {@link UiElementNode} that represents a View.
@@ -31,26 +29,27 @@
public UiViewEditPart(UiElementNode uiElementNode) {
super(uiElementNode);
}
-
+
@Override
protected IFigure createFigure() {
- Label f = new Label();
+ IFigure f = new ElementFigure();
+ f.setLayoutManager(new XYLayout());
return f;
}
-
- @Override
- protected void hideSelection() {
- IFigure f = getFigure();
- if (f instanceof Label) {
- f.setBorder(null);
- }
- }
@Override
protected void showSelection() {
IFigure f = getFigure();
- if (f instanceof Label) {
- f.setBorder(new LineBorder(ColorConstants.red, 1));
+ if (f instanceof ElementFigure) {
+ ((ElementFigure) f).setSelected(true);
+ }
+ }
+
+ @Override
+ protected void hideSelection() {
+ IFigure f = getFigure();
+ if (f instanceof ElementFigure) {
+ ((ElementFigure) f).setSelected(false);
}
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewTreeEditPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiViewTreeEditPart.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewTreeEditPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiViewTreeEditPart.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/uimodel/UiViewElementNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/uimodel/UiViewElementNode.java
similarity index 76%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/uimodel/UiViewElementNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/uimodel/UiViewElementNode.java
index 75cf4b6..45cbc77 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/uimodel/UiViewElementNode.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/uimodel/UiViewElementNode.java
@@ -16,14 +16,20 @@
package com.android.ide.eclipse.editors.layout.uimodel;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
-import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor;
import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+import com.android.sdklib.IAndroidTarget;
+
+import org.eclipse.core.resources.IProject;
+
+import java.util.List;
/**
* Specialized version of {@link UiElementNode} for the {@link ViewElementDescriptor}s.
@@ -59,12 +65,26 @@
// Limitation: right now the layout behaves as if everything was
// owned by a FrameLayout.
// TODO replace by something user-configurable.
- for (ElementDescriptor desc : LayoutDescriptors.getInstance().getLayoutDescriptors()) {
- if (desc instanceof ViewElementDescriptor &&
- desc.getXmlName().equals(AndroidConstants.CLASS_FRAMELAYOUT)) {
- layout_attrs = ((ViewElementDescriptor) desc).getLayoutAttributes();
- need_xmlns = true;
- break;
+
+ List<ElementDescriptor> layoutDescriptors = null;
+ IProject project = getEditor().getProject();
+ if (project != null) {
+ Sdk currentSdk = Sdk.getCurrent();
+ IAndroidTarget target = currentSdk.getTarget(project);
+ if (target != null) {
+ AndroidTargetData data = currentSdk.getTargetData(target);
+ layoutDescriptors = data.getLayoutDescriptors().getLayoutDescriptors();
+ }
+ }
+
+ if (layoutDescriptors != null) {
+ for (ElementDescriptor desc : layoutDescriptors) {
+ if (desc instanceof ViewElementDescriptor &&
+ desc.getXmlName().equals(AndroidConstants.CLASS_FRAMELAYOUT)) {
+ layout_attrs = ((ViewElementDescriptor) desc).getLayoutAttributes();
+ need_xmlns = true;
+ break;
+ }
}
}
} else if (ui_parent instanceof UiViewElementNode){
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestContentAssist.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestContentAssist.java
similarity index 79%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestContentAssist.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestContentAssist.java
index e43c984..b40e458 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestContentAssist.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestContentAssist.java
@@ -16,9 +16,8 @@
package com.android.ide.eclipse.editors.manifest;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.editors.AndroidContentAssist;
-import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
/**
* Content Assist Processor for AndroidManifest.xml
@@ -29,6 +28,6 @@
* Constructor for ManifestContentAssist
*/
public ManifestContentAssist() {
- super(new ElementDescriptor[] { AndroidManifestDescriptors.MANIFEST_ELEMENT });
+ super(AndroidTargetData.DESCRIPTOR_MANIFEST);
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestEditor.java
similarity index 66%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestEditor.java
index 666a066..d0f8d7b 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestEditor.java
@@ -16,10 +16,11 @@
package com.android.ide.eclipse.editors.manifest;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidXPathFactory;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
import com.android.ide.eclipse.editors.manifest.pages.ApplicationPage;
@@ -59,19 +60,30 @@
/** Root node of the UI element hierarchy */
private UiElementNode mUiManifestNode;
- /** Listener to update the root node if the resource framework changes */
- private Runnable mResourceRefreshListener;
/** The Application Page tab */
private ApplicationPage mAppPage;
/** The Overview Manifest Page tab */
private OverviewPage mOverviewPage;
+ /** The Permission Page tab */
+ private PermissionPage mPermissionPage;
+ /** The Instrumentation Page tab */
+ private InstrumentationPage mInstrumentationPage;
+
+ private IFileListener mMarkerMonitor;
+
/**
* Creates the form editor for AndroidManifest.xml.
*/
public ManifestEditor() {
super();
- initUiManifestNode();
+ }
+
+ @Override
+ public void dispose() {
+ super.dispose();
+
+ ResourceMonitor.getMonitor().removeFileListener(mMarkerMonitor);
}
/**
@@ -83,16 +95,19 @@
return mUiManifestNode;
}
- // ---- Base Class Overrides ----
-
- @Override
- public void dispose() {
- if (mResourceRefreshListener != null) {
- EditorsPlugin.getDefault().removeResourceChangedListener(mResourceRefreshListener);
- mResourceRefreshListener = null;
+ /**
+ * Returns the Manifest descriptors for the file being edited.
+ */
+ public AndroidManifestDescriptors getManifestDescriptors() {
+ AndroidTargetData data = getTargetData();
+ if (data != null) {
+ return data.getManifestDescriptors();
}
- super.dispose();
+
+ return null;
}
+
+ // ---- Base Class Overrides ----
/**
* Returns whether the "save as" operation is supported by this editor.
@@ -115,10 +130,10 @@
try {
addPage(mOverviewPage = new OverviewPage(this));
addPage(mAppPage = new ApplicationPage(this));
- addPage(new PermissionPage(this));
- addPage(new InstrumentationPage(this));
+ addPage(mPermissionPage = new PermissionPage(this));
+ addPage(mInstrumentationPage = new InstrumentationPage(this));
} catch (PartInitException e) {
- EditorsPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
+ AdtPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
}
}
@@ -130,6 +145,7 @@
super.setInput(input);
IFile inputFile = getInputFile();
if (inputFile != null) {
+ startMonitoringMarkers();
setPartName(String.format("%1$s Manifest", inputFile.getProject().getName()));
}
}
@@ -141,29 +157,54 @@
*/
@Override
protected void xmlModelChanged(Document xml_doc) {
- mUiManifestNode.setXmlDocument(xml_doc);
- if (xml_doc != null) {
+ // create the ui root node on demand.
+ initUiRootNode(false /*force*/);
+
+ loadFromXml(xml_doc);
+
+ super.xmlModelChanged(xml_doc);
+ }
+
+ private void loadFromXml(Document xmlDoc) {
+ mUiManifestNode.setXmlDocument(xmlDoc);
+ if (xmlDoc != null) {
ElementDescriptor manifest_desc = mUiManifestNode.getDescriptor();
try {
XPath xpath = AndroidXPathFactory.newXPath();
Node node = (Node) xpath.evaluate("/" + manifest_desc.getXmlName(), //$NON-NLS-1$
- xml_doc,
+ xmlDoc,
XPathConstants.NODE);
assert node != null && node.getNodeName().equals(manifest_desc.getXmlName());
// Refresh the manifest UI node and all its descendants
mUiManifestNode.loadFromXmlNode(node);
-
- startMonitoringMarkers();
} catch (XPathExpressionException e) {
- EditorsPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$
+ AdtPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$
manifest_desc.getXmlName());
}
}
-
- super.xmlModelChanged(xml_doc);
}
+ private void onDescriptorsChanged(UiElementNode oldManifestNode) {
+ mUiManifestNode.reloadFromXmlNode(oldManifestNode.getXmlNode());
+
+ if (mOverviewPage != null) {
+ mOverviewPage.refreshUiApplicationNode();
+ }
+
+ if (mAppPage != null) {
+ mAppPage.refreshUiApplicationNode();
+ }
+
+ if (mPermissionPage != null) {
+ mPermissionPage.refreshUiNode();
+ }
+
+ if (mInstrumentationPage != null) {
+ mInstrumentationPage.refreshUiNode();
+ }
+ }
+
/**
* Reads and processes the current markers and adds a listener for marker changes.
*/
@@ -172,13 +213,15 @@
if (inputFile != null) {
updateFromExistingMarkers(inputFile);
- ResourceMonitor.getMonitor().addFileListener(new IFileListener() {
+ mMarkerMonitor = new IFileListener() {
public void fileChanged(IFile file, IMarkerDelta[] markerDeltas, int kind) {
if (file.equals(inputFile)) {
processMarkerChanges(markerDeltas);
}
}
- }, IResourceDelta.CHANGED);
+ };
+
+ ResourceMonitor.getMonitor().addFileListener(mMarkerMonitor, IResourceDelta.CHANGED);
}
}
@@ -192,14 +235,22 @@
// get the markers for the file
IMarker[] markers = inputFile.findMarkers(AndroidConstants.MARKER_ANDROID, true,
IResource.DEPTH_ZERO);
+
+ AndroidManifestDescriptors desc = getManifestDescriptors();
+ if (desc != null) {
+ ElementDescriptor appElement = desc.getApplicationElement();
+
+ if (appElement != null) {
+ UiElementNode app_ui_node = mUiManifestNode.findUiChildNode(
+ appElement.getXmlName());
+ List<UiElementNode> children = app_ui_node.getUiChildren();
- UiElementNode app_ui_node = mUiManifestNode.findUiChildNode(
- AndroidManifestDescriptors.APPLICATION_ELEMENT.getXmlName());
- List<UiElementNode> children = app_ui_node.getUiChildren();
-
- for (IMarker marker : markers) {
- processMarker(marker, children, IResourceDelta.ADDED);
+ for (IMarker marker : markers) {
+ processMarker(marker, children, IResourceDelta.ADDED);
+ }
+ }
}
+
} catch (CoreException e) {
// findMarkers can throw an exception, in which case, we'll do nothing.
}
@@ -210,12 +261,15 @@
* @param markerDeltas the list of {@link IMarkerDelta}
*/
private void processMarkerChanges(IMarkerDelta[] markerDeltas) {
- UiElementNode app_ui_node = mUiManifestNode.findUiChildNode(
- AndroidManifestDescriptors.APPLICATION_ELEMENT.getXmlName());
- List<UiElementNode> children = app_ui_node.getUiChildren();
-
- for (IMarkerDelta markerDelta : markerDeltas) {
- processMarker(markerDelta.getMarker(), children, markerDelta.getKind());
+ AndroidManifestDescriptors descriptors = getManifestDescriptors();
+ if (descriptors != null && descriptors.getApplicationElement() != null) {
+ UiElementNode app_ui_node = mUiManifestNode.findUiChildNode(
+ descriptors.getApplicationElement().getXmlName());
+ List<UiElementNode> children = app_ui_node.getUiChildren();
+
+ for (IMarkerDelta markerDelta : markerDeltas) {
+ processMarker(markerDelta.getMarker(), children, markerDelta.getKind());
+ }
}
}
@@ -259,56 +313,62 @@
/**
* Creates the initial UI Root Node, including the known mandatory elements.
+ * @param force if true, a new UiManifestNode is recreated even if it already exists.
*/
- private void initUiManifestNode() {
+ @Override
+ protected void initUiRootNode(boolean force) {
// The manifest UI node is always created, even if there's no corresponding XML node.
- if (mUiManifestNode == null) {
- ElementDescriptor manifest_desc = AndroidManifestDescriptors.MANIFEST_ELEMENT;
- mUiManifestNode = manifest_desc.createUiNode();
+ if (mUiManifestNode != null && force == false) {
+ return;
+ }
+
+
+ AndroidManifestDescriptors manifestDescriptor = getManifestDescriptors();
+
+ if (manifestDescriptor != null) {
+ // save the old manifest node if it exists
+ UiElementNode oldManifestNode = mUiManifestNode;
+
+ ElementDescriptor manifestElement = manifestDescriptor.getManifestElement();
+ mUiManifestNode = manifestElement.createUiNode();
mUiManifestNode.setEditor(this);
// Similarly, always create the /manifest/application and /manifest/uses-sdk nodes
- ElementDescriptor app_desc = AndroidManifestDescriptors.APPLICATION_ELEMENT;
+ ElementDescriptor appElement = manifestDescriptor.getApplicationElement();
boolean present = false;
for (UiElementNode ui_node : mUiManifestNode.getUiChildren()) {
- if (ui_node.getDescriptor() == app_desc) {
+ if (ui_node.getDescriptor() == appElement) {
present = true;
break;
}
}
if (!present) {
- mUiManifestNode.appendNewUiChild(app_desc);
+ mUiManifestNode.appendNewUiChild(appElement);
}
- app_desc = AndroidManifestDescriptors.USES_SDK_ELEMENT;
+ appElement = manifestDescriptor.getUsesSdkElement();
present = false;
for (UiElementNode ui_node : mUiManifestNode.getUiChildren()) {
- if (ui_node.getDescriptor() == app_desc) {
+ if (ui_node.getDescriptor() == appElement) {
present = true;
break;
}
}
if (!present) {
- mUiManifestNode.appendNewUiChild(app_desc);
+ mUiManifestNode.appendNewUiChild(appElement);
}
- // Add a listener to refresh the root node if the resource framework changes
- // by forcing it to parse its own XML
- mResourceRefreshListener = new Runnable() {
- public void run() {
- commitPages(false /* onSave */);
-
- mUiManifestNode.reloadFromXmlNode(mUiManifestNode.getXmlNode());
- if (mOverviewPage != null) {
- mOverviewPage.refreshUiApplicationNode();
- }
- if (mAppPage != null) {
- mAppPage.refreshUiApplicationNode();
- }
- }
- };
- EditorsPlugin.getDefault().addResourceChangedListener(mResourceRefreshListener);
- mResourceRefreshListener.run();
+ if (oldManifestNode != null) {
+ onDescriptorsChanged(oldManifestNode);
+ }
+ } else {
+ // create a dummy descriptor/uinode until we have real descriptors
+ ElementDescriptor desc = new ElementDescriptor("manifest", //$NON-NLS-1$
+ "temporary descriptors due to missing decriptors", //$NON-NLS-1$
+ null /*tooltip*/, null /*sdk_url*/, null /*attributes*/,
+ null /*children*/, false /*mandatory*/);
+ mUiManifestNode = desc.createUiNode();
+ mUiManifestNode.setEditor(this);
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditorContributor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestEditorContributor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditorContributor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestEditorContributor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestSourceViewerConfig.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestSourceViewerConfig.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestSourceViewerConfig.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestSourceViewerConfig.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java
similarity index 88%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java
index 171eaee..87a14ad 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java
@@ -16,17 +16,18 @@
package com.android.ide.eclipse.editors.manifest.descriptors;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.resources.DeclareStyleableInfo;
import com.android.ide.eclipse.common.resources.ResourceType;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
+import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
import com.android.ide.eclipse.editors.descriptors.ListAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.ReferenceAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor;
+import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
import org.eclipse.core.runtime.IStatus;
@@ -45,7 +46,7 @@
* However their sub-elements and attributes are created only when the SDK changes or is
* loaded the first time.
*/
-public class AndroidManifestDescriptors {
+public final class AndroidManifestDescriptors implements IDescriptorProvider {
private static final String MANIFEST_NODE_NAME = "manifest"; //$NON-NLS-1$
private static final String ANDROID_MANIFEST_STYLEABLE = "AndroidManifest"; //$NON-NLS-1$
@@ -57,28 +58,28 @@
public static final String PACKAGE_ATTR = "package"; //$NON-NLS-1$
/** The {@link ElementDescriptor} for the root Manifest element. */
- public static final ElementDescriptor MANIFEST_ELEMENT;
+ private final ElementDescriptor MANIFEST_ELEMENT;
/** The {@link ElementDescriptor} for the root Application element. */
- public static final ElementDescriptor APPLICATION_ELEMENT;
+ private final ElementDescriptor APPLICATION_ELEMENT;
/** The {@link ElementDescriptor} for the root Instrumentation element. */
- public static final ElementDescriptor INTRUMENTATION_ELEMENT;
+ private final ElementDescriptor INTRUMENTATION_ELEMENT;
/** The {@link ElementDescriptor} for the root Permission element. */
- public static final ElementDescriptor PERMISSION_ELEMENT;
+ private final ElementDescriptor PERMISSION_ELEMENT;
/** The {@link ElementDescriptor} for the root UsesPermission element. */
- public static final ElementDescriptor USES_PERMISSION_ELEMENT;
+ private final ElementDescriptor USES_PERMISSION_ELEMENT;
/** The {@link ElementDescriptor} for the root UsesSdk element. */
- public static final ElementDescriptor USES_SDK_ELEMENT;
+ private final ElementDescriptor USES_SDK_ELEMENT;
/** The {@link ElementDescriptor} for the root PermissionGroup element. */
- public static final ElementDescriptor PERMISSION_GROUP_ELEMENT;
+ private final ElementDescriptor PERMISSION_GROUP_ELEMENT;
/** The {@link ElementDescriptor} for the root PermissionTree element. */
- public static final ElementDescriptor PERMISSION_TREE_ELEMENT;
+ private final ElementDescriptor PERMISSION_TREE_ELEMENT;
/** Private package attribute for the manifest element. Needs to be handled manually. */
- private static final TextAttributeDescriptor PACKAGE_ATTR_DESC;
+ private final TextAttributeDescriptor PACKAGE_ATTR_DESC;
- static {
+ public AndroidManifestDescriptors() {
APPLICATION_ELEMENT = createElement("application", null, true); //$NON-NLS-1$ + no child & mandatory
INTRUMENTATION_ELEMENT = createElement("instrumentation"); //$NON-NLS-1$
@@ -109,6 +110,46 @@
null /* nsUri */,
"This attribute gives a unique name for the package, using a Java-style naming convention to avoid name collisions.\nFor example, applications published by Google could have names of the form com.google.app.appname");
}
+
+ public ElementDescriptor[] getRootElementDescriptors() {
+ return new ElementDescriptor[] { MANIFEST_ELEMENT };
+ }
+
+ public ElementDescriptor getDescriptor() {
+ return getManifestElement();
+ }
+
+ public ElementDescriptor getApplicationElement() {
+ return APPLICATION_ELEMENT;
+ }
+
+ public ElementDescriptor getManifestElement() {
+ return MANIFEST_ELEMENT;
+ }
+
+ public ElementDescriptor getUsesSdkElement() {
+ return USES_SDK_ELEMENT;
+ }
+
+ public ElementDescriptor getInstrumentationElement() {
+ return INTRUMENTATION_ELEMENT;
+ }
+
+ public ElementDescriptor getPermissionElement() {
+ return PERMISSION_ELEMENT;
+ }
+
+ public ElementDescriptor getUsesPermissionElement() {
+ return USES_PERMISSION_ELEMENT;
+ }
+
+ public ElementDescriptor getPermissionGroupElement() {
+ return PERMISSION_GROUP_ELEMENT;
+ }
+
+ public ElementDescriptor getPermissionTreeElement() {
+ return PERMISSION_TREE_ELEMENT;
+ }
/**
* Updates the document descriptor.
@@ -118,7 +159,7 @@
*
* @param manifestMap The map style => attributes from the attrs_manifest.xml file
*/
- public static synchronized void updateDescriptors(
+ public synchronized void updateDescriptors(
Map<String, DeclareStyleableInfo> manifestMap) {
XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor(
@@ -177,7 +218,7 @@
sanityCheck(manifestMap, MANIFEST_ELEMENT);
}
-
+
/**
* Sets up an attribute override for ANDROID_NAME_ATTR using a ClassAttributeDescriptor
* with the specified class name.
@@ -223,7 +264,7 @@
* <p/>
* Creates an element with no attribute overrides.
*/
- private static ElementDescriptor createElement(
+ private ElementDescriptor createElement(
String xmlName,
ElementDescriptor[] childrenElements,
boolean mandatory) {
@@ -243,7 +284,7 @@
* <p/>
* This version creates an element not mandatory.
*/
- private static ElementDescriptor createElement(String xmlName) {
+ private ElementDescriptor createElement(String xmlName) {
// Creates an element with no child and not mandatory
return createElement(xmlName, null, false);
}
@@ -253,7 +294,7 @@
* (based on the attribute XML name.)
* The attribute is inserted at the beginning of the attribute list.
*/
- private static void insertAttribute(ElementDescriptor element, AttributeDescriptor newAttr) {
+ private void insertAttribute(ElementDescriptor element, AttributeDescriptor newAttr) {
AttributeDescriptor[] attributes = element.getAttributes();
for (AttributeDescriptor attr : attributes) {
if (attr.getXmlLocalName().equals(newAttr.getXmlLocalName())) {
@@ -285,7 +326,7 @@
* @param styleName The name of the {@link ElementDescriptor} to inflate. Its XML local name
* will be guessed automatically from the style name.
*/
- private static void inflateElement(
+ private void inflateElement(
Map<String, DeclareStyleableInfo> styleMap,
Map<String, Object> overrides,
HashMap<String, ElementDescriptor> existingElementDescs,
@@ -343,7 +384,7 @@
* <p/>
* Capitalizes the first letter and replace non-alphabet by a space followed by a capital.
*/
- private static String getUiName(String xmlName) {
+ private String getUiName(String xmlName) {
StringBuilder sb = new StringBuilder();
boolean capitalize = true;
@@ -376,7 +417,7 @@
* - application => AndroidManifestApplication
* - uses-permission => AndroidManifestUsesPermission
*/
- private static String guessStyleName(String xmlName) {
+ private String guessStyleName(String xmlName) {
StringBuilder sb = new StringBuilder();
if (!xmlName.equals(MANIFEST_NODE_NAME)) {
@@ -403,7 +444,7 @@
* manifestMap are actually defined in the actual element descriptors and reachable from
* the manifestElement root node.
*/
- private static void sanityCheck(Map<String, DeclareStyleableInfo> manifestMap,
+ private void sanityCheck(Map<String, DeclareStyleableInfo> manifestMap,
ElementDescriptor manifestElement) {
TreeSet<String> elementsDeclared = new TreeSet<String>();
findAllElementNames(manifestElement, elementsDeclared);
@@ -434,8 +475,8 @@
}
}
- EditorsPlugin.log(IStatus.WARNING, "%s", sb.toString());
- EditorsPlugin.printToConsole(null, sb);
+ AdtPlugin.log(IStatus.WARNING, "%s", sb.toString());
+ AdtPlugin.printToConsole((String)null, sb);
sb.setLength(0);
}
@@ -448,8 +489,8 @@
}
}
- EditorsPlugin.log(IStatus.WARNING, "%s", sb.toString());
- EditorsPlugin.printToConsole(null, sb);
+ AdtPlugin.log(IStatus.WARNING, "%s", sb.toString());
+ AdtPlugin.printToConsole((String)null, sb);
}
}
@@ -459,7 +500,7 @@
*
* @return The XML local name for a given style name.
*/
- private static String guessXmlName(String name) {
+ private String guessXmlName(String name) {
StringBuilder sb = new StringBuilder();
if (ANDROID_MANIFEST_STYLEABLE.equals(name)) {
sb.append(MANIFEST_NODE_NAME);
@@ -486,7 +527,7 @@
* <p/>
* Note: this assumes no circular reference in the tree of {@link ElementDescriptor}s.
*/
- private static void findAllElementNames(ElementDescriptor element, TreeSet<String> declared) {
+ private void findAllElementNames(ElementDescriptor element, TreeSet<String> declared) {
declared.add(element.getXmlName());
for (ElementDescriptor desc : element.getChildren()) {
findAllElementNames(desc, declared);
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ApplicationAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ApplicationAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ApplicationAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ApplicationAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ClassAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ClassAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ClassAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ClassAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/InstrumentationAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/InstrumentationAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/InstrumentationAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/InstrumentationAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ManifestElementDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ManifestElementDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ManifestElementDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ManifestElementDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PackageAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/PackageAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PackageAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/PackageAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PostActivityCreationAction.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/PostActivityCreationAction.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PostActivityCreationAction.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/PostActivityCreationAction.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PostReceiverCreationAction.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/PostReceiverCreationAction.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PostReceiverCreationAction.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/PostReceiverCreationAction.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ThemeAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ThemeAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ThemeAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ThemeAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiManifestElementNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiManifestElementNode.java
similarity index 92%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiManifestElementNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiManifestElementNode.java
index 10ce50d..79295a8 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiManifestElementNode.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiManifestElementNode.java
@@ -64,12 +64,15 @@
getXmlNode() instanceof Element &&
getXmlNode().hasAttributes()) {
+ AndroidManifestDescriptors manifestDescriptors =
+ getAndroidTarget().getManifestDescriptors();
+
// Application and Manifest nodes have a special treatment: they are unique nodes
// so we don't bother trying to differentiate their strings and we fall back to
// just using the UI name below.
ElementDescriptor desc = getDescriptor();
- if (desc != AndroidManifestDescriptors.MANIFEST_ELEMENT &&
- desc != AndroidManifestDescriptors.APPLICATION_ELEMENT) {
+ if (desc != manifestDescriptors.getManifestElement() &&
+ desc != manifestDescriptors.getApplicationElement()) {
Element elem = (Element) getXmlNode();
String attr = elem.getAttributeNS(AndroidConstants.NS_RESOURCES,
AndroidManifestDescriptors.ANDROID_NAME_ATTR);
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiPackageAttributeNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiPackageAttributeNode.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiPackageAttributeNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiPackageAttributeNode.java
index 5e02273..02fb44f 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiPackageAttributeNode.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiPackageAttributeNode.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.manifest.model;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor;
import com.android.ide.eclipse.editors.ui.SectionHelper;
@@ -184,7 +184,7 @@
JavaCore.create(project), 0);
dlg.setTitle("Select Android Package");
dlg.setMessage("Select the package for the Android project.");
- dlg.setDefaultImage(EditorsPlugin.getAndroidLogo());
+ SelectionDialog.setDefaultImage(AdtPlugin.getAndroidLogo());
if (dlg.open() == Window.OK) {
Object[] results = dlg.getResult();
@@ -212,13 +212,13 @@
IProject project = getProject();
if (project == null) {
- EditorsPlugin.log(IStatus.ERROR, "Failed to get project for UiPackageAttribute"); //$NON-NLS-1$
+ AdtPlugin.log(IStatus.ERROR, "Failed to get project for UiPackageAttribute"); //$NON-NLS-1$
return;
}
IWorkbenchPartSite site = getUiParent().getEditor().getSite();
if (site == null) {
- EditorsPlugin.log(IStatus.ERROR, "Failed to get editor site for UiPackageAttribute"); //$NON-NLS-1$
+ AdtPlugin.log(IStatus.ERROR, "Failed to get editor site for UiPackageAttribute"); //$NON-NLS-1$
return;
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationAttributesPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationAttributesPart.java
similarity index 98%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationAttributesPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationAttributesPart.java
index 25bdb0e..01b0f8f 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationAttributesPart.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationAttributesPart.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.manifest.pages;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.ide.eclipse.editors.manifest.ManifestEditor;
@@ -130,7 +130,7 @@
} else {
// The XML has an extra attribute which wasn't declared in
// AndroidManifestDescriptors. This is not a problem, we just ignore it.
- EditorsPlugin.log(IStatus.WARNING,
+ AdtPlugin.log(IStatus.WARNING,
"Attribute %1$s not declared in node %2$s, ignored.", //$NON-NLS-1$
attr_desc.getXmlLocalName(),
uiElementNode.getDescriptor().getXmlName());
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationPage.java
similarity index 89%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationPage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationPage.java
index 1823278..77527f0 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationPage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationPage.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.manifest.pages;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.manifest.ManifestEditor;
import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
@@ -67,7 +67,7 @@
super.createFormContent(managedForm);
ScrolledForm form = managedForm.getForm();
form.setText("Android Manifest Application");
- form.setImage(EditorsPlugin.getAndroidLogo());
+ form.setImage(AdtPlugin.getAndroidLogo());
UiElementNode appUiNode = getUiApplicationNode();
@@ -96,8 +96,14 @@
* exists, even if there is no matching XML node.
*/
private UiElementNode getUiApplicationNode() {
- ElementDescriptor desc = AndroidManifestDescriptors.APPLICATION_ELEMENT;
- return mEditor.getUiRootNode().findUiChildNode(desc.getXmlName());
+ AndroidManifestDescriptors manifestDescriptor = mEditor.getManifestDescriptors();
+ if (manifestDescriptor != null) {
+ ElementDescriptor desc = manifestDescriptor.getApplicationElement();
+ return mEditor.getUiRootNode().findUiChildNode(desc.getXmlName());
+ } else {
+ // return the ui root node, as a dummy application root node.
+ return mEditor.getUiRootNode();
+ }
}
/**
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationToggle.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationToggle.java
similarity index 86%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationToggle.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationToggle.java
index daec98c..139575d 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationToggle.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationToggle.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.manifest.pages;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.manifest.ManifestEditor;
import com.android.ide.eclipse.editors.ui.UiElementPart;
@@ -130,10 +130,10 @@
if (tooltip != null) {
tooltip = DescriptorsUtils.formatFormText(tooltip,
getUiElementNode().getDescriptor(),
- FrameworkResourceManager.getInstance().getDocumentationBaseUrl());
+ Sdk.getCurrent().getDocumentationBaseUrl());
mTooltipFormText.setText(tooltip, true /* parseTags */, true /* expandURLs */);
- mTooltipFormText.setImage(DescriptorsUtils.IMAGE_KEY, EditorsPlugin.getAndroidLogo());
+ mTooltipFormText.setImage(DescriptorsUtils.IMAGE_KEY, AdtPlugin.getAndroidLogo());
mTooltipFormText.addHyperlinkListener(getEditor().createHyperlinkListener());
isVisible = true;
}
@@ -156,23 +156,32 @@
public void widgetSelected(SelectionEvent e) {
super.widgetSelected(e);
if (!mInternalModification && getUiElementNode() != null) {
- getUiElementNode().getEditor().editXmlModel(new Runnable() {
- public void run() {
- if (mCheckbox.getSelection()) {
- // The user wants an <application> node. Either restore a previous one
- // or create a full new one.
- boolean create = true;
- if (mUndoXmlNode != null) {
- create = !restoreApplicationNode();
+ getUiElementNode().getEditor().wrapUndoRecording(
+ mCheckbox.getSelection()
+ ? "Create or restore Application node"
+ : "Remove Application node",
+ new Runnable() {
+ public void run() {
+ getUiElementNode().getEditor().editXmlModel(new Runnable() {
+ public void run() {
+ if (mCheckbox.getSelection()) {
+ // The user wants an <application> node.
+ // Either restore a previous one
+ // or create a full new one.
+ boolean create = true;
+ if (mUndoXmlNode != null) {
+ create = !restoreApplicationNode();
+ }
+ if (create) {
+ getUiElementNode().createXmlNode();
+ }
+ } else {
+ // Users no longer wants the <application> node.
+ removeApplicationNode();
+ }
+ }
+ });
}
- if (create) {
- getUiElementNode().createXmlNode();
- }
- } else {
- // Users no longer wants the <application> node.
- removeApplicationNode();
- }
- }
});
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/InstrumentationPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/InstrumentationPage.java
similarity index 65%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/InstrumentationPage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/InstrumentationPage.java
index 8eb6765..86d0dd1 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/InstrumentationPage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/InstrumentationPage.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.manifest.pages;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.manifest.ManifestEditor;
import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
@@ -37,6 +37,8 @@
/** Container editor */
ManifestEditor mEditor;
+ private UiTreeBlock mTreeBlock;
+
public InstrumentationPage(ManifestEditor editor) {
super(editor, PAGE_ID, "Instrumentation"); // tab's label, keep it short
mEditor = editor;
@@ -52,14 +54,39 @@
super.createFormContent(managedForm);
ScrolledForm form = managedForm.getForm();
form.setText("Android Manifest Instrumentation");
- form.setImage(EditorsPlugin.getAndroidLogo());
+ form.setImage(AdtPlugin.getAndroidLogo());
UiElementNode manifest = mEditor.getUiRootNode();
- UiTreeBlock block = new UiTreeBlock(mEditor, manifest,
+ AndroidManifestDescriptors manifestDescriptor = mEditor.getManifestDescriptors();
+
+ ElementDescriptor[] descriptorFilters = null;
+ if (manifestDescriptor != null) {
+ descriptorFilters = new ElementDescriptor[] {
+ manifestDescriptor.getInstrumentationElement(),
+ };
+ }
+
+ mTreeBlock = new UiTreeBlock(mEditor, manifest,
true /* autoCreateRoot */,
- new ElementDescriptor[] { AndroidManifestDescriptors.INTRUMENTATION_ELEMENT },
+ descriptorFilters,
"Instrumentation",
"List of instrumentations defined in the manifest");
- block.createContent(managedForm);
+ mTreeBlock.createContent(managedForm);
+ }
+
+ /**
+ * Changes and refreshes the Application UI node handled by the sub parts.
+ */
+ public void refreshUiNode() {
+ if (mTreeBlock != null) {
+ UiElementNode manifest = mEditor.getUiRootNode();
+ AndroidManifestDescriptors manifestDescriptor = mEditor.getManifestDescriptors();
+
+ mTreeBlock.changeRootAndDescriptors(manifest,
+ new ElementDescriptor[] {
+ manifestDescriptor.getInstrumentationElement()
+ },
+ true /* refresh */);
+ }
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewExportPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewExportPart.java
similarity index 91%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewExportPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewExportPart.java
index 4e6521c..66af84c 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewExportPart.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewExportPart.java
@@ -49,9 +49,12 @@
StringBuffer buf = new StringBuffer();
buf.append("<form><li><a href=\"wizard\">"); //$NON-NLS-1$
- buf.append("Use the export wizard");
- buf.append("</a></li><li><a href=\"manual\">"); //$NON-NLS-1$
- buf.append("Export an unsigned apk");
+ buf.append("Use the Export Wizard");
+ buf.append("</a>"); //$NON-NLS-1$
+ buf.append(" to export and sign an APK");
+ buf.append("</li>"); //$NON-NLS-1$
+ buf.append("<li><a href=\"manual\">"); //$NON-NLS-1$
+ buf.append("Export an unsigned APK");
buf.append("</a>"); //$NON-NLS-1$
buf.append(" and sign it manually");
buf.append("</li></form>"); //$NON-NLS-1$
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java
similarity index 87%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java
index 182c6f3..026b760 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java
@@ -49,12 +49,19 @@
* and can't be null, by design, because it's a mandatory node.
*/
private static UiElementNode getManifestUiNode(ManifestEditor editor) {
- ElementDescriptor desc = AndroidManifestDescriptors.MANIFEST_ELEMENT;
- if (editor.getUiRootNode().getDescriptor() == desc) {
- return editor.getUiRootNode();
- } else {
- return editor.getUiRootNode().findUiChildNode(desc.getXmlName());
+ AndroidManifestDescriptors manifestDescriptors = editor.getManifestDescriptors();
+ if (manifestDescriptors != null) {
+ ElementDescriptor desc = manifestDescriptors.getManifestElement();
+ if (editor.getUiRootNode().getDescriptor() == desc) {
+ return editor.getUiRootNode();
+ } else {
+ return editor.getUiRootNode().findUiChildNode(desc.getXmlName());
+ }
}
+
+ // No manifest descriptor: we have a dummy UiRootNode, so we return that.
+ // The editor will be reloaded once we have the proper descriptors anyway.
+ return editor.getUiRootNode();
}
/**
@@ -62,8 +69,15 @@
* exists, even if there is no matching XML node.
*/
private UiElementNode getUsesSdkUiNode(ManifestEditor editor) {
- ElementDescriptor desc = AndroidManifestDescriptors.USES_SDK_ELEMENT;
- return editor.getUiRootNode().findUiChildNode(desc.getXmlName());
+ AndroidManifestDescriptors manifestDescriptors = editor.getManifestDescriptors();
+ if (manifestDescriptors != null) {
+ ElementDescriptor desc = manifestDescriptors.getUsesSdkElement();
+ return editor.getUiRootNode().findUiChildNode(desc.getXmlName());
+ }
+
+ // No manifest descriptor: we have a dummy UiRootNode, so we return that.
+ // The editor will be reloaded once we have the proper descriptors anyway.
+ return editor.getUiRootNode();
}
/**
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewLinksPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewLinksPart.java
similarity index 66%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewLinksPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewLinksPart.java
index 7675fa2..d637a8f 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewLinksPart.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewLinksPart.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.manifest.pages;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.manifest.ManifestEditor;
import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
@@ -33,8 +33,12 @@
*/
final class OverviewLinksPart extends ManifestSectionPart {
+ private final ManifestEditor mEditor;
+ private FormText mFormText;
+
public OverviewLinksPart(Composite body, FormToolkit toolkit, ManifestEditor editor) {
super(body, toolkit, Section.TWISTIE | Section.EXPANDED, true /* description */);
+ mEditor = editor;
Section section = getSection();
section.setText("Links");
section.setDescription("The content of the Android Manifest is made up of three sections. You can also edit the XML directly.");
@@ -75,13 +79,40 @@
buf.append("</li>"); //$NON-NLS-1$
buf.append("</form>"); //$NON-NLS-1$
- FormText text = createFormText(table, toolkit, true, buf.toString(),
+ mFormText = createFormText(table, toolkit, true, buf.toString(),
false /* setupLayoutData */);
- text.setImage("android_img", EditorsPlugin.getAndroidLogo());
- text.setImage("app_img", getIcon(AndroidManifestDescriptors.APPLICATION_ELEMENT));
- text.setImage("perm_img", getIcon(AndroidManifestDescriptors.PERMISSION_ELEMENT));
- text.setImage("inst_img", getIcon(AndroidManifestDescriptors.INTRUMENTATION_ELEMENT));
- text.addHyperlinkListener(editor.createHyperlinkListener());
+
+ AndroidManifestDescriptors manifestDescriptor = editor.getManifestDescriptors();
+
+ Image androidLogo = AdtPlugin.getAndroidLogo();
+ mFormText.setImage("android_img", androidLogo); //$NON-NLS-1$
+
+ if (manifestDescriptor != null) {
+ mFormText.setImage("app_img", getIcon(manifestDescriptor.getApplicationElement())); //$NON-NLS-1$
+ mFormText.setImage("perm_img", getIcon(manifestDescriptor.getPermissionElement())); //$NON-NLS-1$
+ mFormText.setImage("inst_img", getIcon(manifestDescriptor.getInstrumentationElement())); //$NON-NLS-1$
+ } else {
+ mFormText.setImage("app_img", androidLogo); //$NON-NLS-1$
+ mFormText.setImage("perm_img", androidLogo); //$NON-NLS-1$
+ mFormText.setImage("inst_img", androidLogo); //$NON-NLS-1$
+ }
+ mFormText.addHyperlinkListener(editor.createHyperlinkListener());
+ }
+
+ /**
+ * Update the UI with information from the new descriptors.
+ * <p/>At this point, this only refreshes the icons.
+ * <p/>
+ * This is called by {@link OverviewPage#refreshUiApplicationNode()} when the
+ * SDK has changed.
+ */
+ public void onSdkChanged() {
+ AndroidManifestDescriptors manifestDescriptor = mEditor.getManifestDescriptors();
+ if (manifestDescriptor != null) {
+ mFormText.setImage("app_img", getIcon(manifestDescriptor.getApplicationElement())); //$NON-NLS-1$
+ mFormText.setImage("perm_img", getIcon(manifestDescriptor.getPermissionElement())); //$NON-NLS-1$
+ mFormText.setImage("inst_img", getIcon(manifestDescriptor.getInstrumentationElement())); //$NON-NLS-1$
+ }
}
private Image getIcon(ElementDescriptor desc) {
@@ -89,6 +120,6 @@
return desc.getIcon();
}
- return EditorsPlugin.getAndroidLogo();
+ return AdtPlugin.getAndroidLogo();
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java
similarity index 87%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java
index 9e8925a..62954bd 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.manifest.pages;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.manifest.ManifestEditor;
import org.eclipse.swt.widgets.Composite;
@@ -43,6 +43,8 @@
ManifestEditor mEditor;
/** Overview part (attributes for manifest) */
private OverviewInfoPart mOverviewPart;
+ /** Overview link part */
+ private OverviewLinksPart mOverviewLinkPart;
public OverviewPage(ManifestEditor editor) {
super(editor, PAGE_ID, "Overview"); // tab's label, user visible, keep it short
@@ -59,7 +61,7 @@
super.createFormContent(managedForm);
ScrolledForm form = managedForm.getForm();
form.setText("Android Manifest Overview");
- form.setImage(EditorsPlugin.getAndroidLogo());
+ form.setImage(AdtPlugin.getAndroidLogo());
Composite body = form.getBody();
FormToolkit toolkit = managedForm.getToolkit();
@@ -69,7 +71,8 @@
mOverviewPart = new OverviewInfoPart(body, toolkit, mEditor);
managedForm.addPart(mOverviewPart);
managedForm.addPart(new OverviewExportPart(this, body, toolkit, mEditor));
- managedForm.addPart(new OverviewLinksPart(body, toolkit, mEditor));
+ mOverviewLinkPart = new OverviewLinksPart(body, toolkit, mEditor);
+ managedForm.addPart(mOverviewLinkPart);
}
/**
@@ -79,5 +82,9 @@
if (mOverviewPart != null) {
mOverviewPart.onSdkChanged();
}
+
+ if (mOverviewLinkPart != null) {
+ mOverviewLinkPart.onSdkChanged();
+ }
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/PermissionPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/PermissionPage.java
similarity index 60%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/PermissionPage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/PermissionPage.java
index a7c0ad5..41ba22e 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/PermissionPage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/PermissionPage.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.manifest.pages;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.manifest.ManifestEditor;
import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
@@ -41,6 +41,8 @@
/** Container editor */
ManifestEditor mEditor;
+ private UiTreeBlock mTreeBlock;
+
public PermissionPage(ManifestEditor editor) {
super(editor, PAGE_ID, "Permissions"); // tab label, keep it short
mEditor = editor;
@@ -56,19 +58,44 @@
super.createFormContent(managedForm);
ScrolledForm form = managedForm.getForm();
form.setText("Android Manifest Permissions");
- form.setImage(EditorsPlugin.getAndroidLogo());
+ form.setImage(AdtPlugin.getAndroidLogo());
UiElementNode manifest = mEditor.getUiRootNode();
- UiTreeBlock block = new UiTreeBlock(mEditor, manifest,
+ AndroidManifestDescriptors manifestDescriptor = mEditor.getManifestDescriptors();
+
+ ElementDescriptor[] descriptorFilters = null;
+ if (manifestDescriptor != null) {
+ descriptorFilters = new ElementDescriptor[] {
+ manifestDescriptor.getPermissionElement(),
+ manifestDescriptor.getUsesPermissionElement(),
+ manifestDescriptor.getPermissionGroupElement(),
+ manifestDescriptor.getPermissionTreeElement()
+ };
+ }
+ mTreeBlock = new UiTreeBlock(mEditor, manifest,
true /* autoCreateRoot */,
- new ElementDescriptor[] {
- AndroidManifestDescriptors.PERMISSION_ELEMENT,
- AndroidManifestDescriptors.USES_PERMISSION_ELEMENT,
- AndroidManifestDescriptors.PERMISSION_GROUP_ELEMENT,
- AndroidManifestDescriptors.PERMISSION_TREE_ELEMENT
- },
+ descriptorFilters,
"Permissions",
"List of permissions defined and used by the manifest");
- block.createContent(managedForm);
+ mTreeBlock.createContent(managedForm);
+ }
+
+ /**
+ * Changes and refreshes the Application UI node handled by the sub parts.
+ */
+ public void refreshUiNode() {
+ if (mTreeBlock != null) {
+ UiElementNode manifest = mEditor.getUiRootNode();
+ AndroidManifestDescriptors manifestDescriptor = mEditor.getManifestDescriptors();
+
+ mTreeBlock.changeRootAndDescriptors(manifest,
+ new ElementDescriptor[] {
+ manifestDescriptor.getPermissionElement(),
+ manifestDescriptor.getUsesPermissionElement(),
+ manifestDescriptor.getPermissionGroupElement(),
+ manifestDescriptor.getPermissionTreeElement()
+ },
+ true /* refresh */);
+ }
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuContentAssist.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuContentAssist.java
similarity index 86%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuContentAssist.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuContentAssist.java
index 57b9a42..bf76d53 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuContentAssist.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuContentAssist.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.menu;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.editors.AndroidContentAssist;
-import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors;
/**
* Content Assist Processor for /res/menu XML files
@@ -28,6 +28,6 @@
* Constructor for LayoutContentAssist
*/
public MenuContentAssist() {
- super(MenuDescriptors.getInstance().getDescriptor().getChildren());
+ super(AndroidTargetData.DESCRIPTOR_MENU);
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuEditor.java
similarity index 73%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuEditor.java
index 4bf02fa..cff1746 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuEditor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuEditor.java
@@ -16,11 +16,12 @@
package com.android.ide.eclipse.editors.menu;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidXPathFactory;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
import org.eclipse.core.resources.IFile;
@@ -40,19 +41,16 @@
*/
public class MenuEditor extends AndroidEditor {
- public static final String ID = "com.android.ide.eclipse.editors.menu.MenuEditor"; //$NON-NLS-1$
+ public static final String ID = AndroidConstants.EDITORS_NAMESPACE + ".menu.MenuEditor"; //$NON-NLS-1$
/** Root node of the UI element hierarchy */
private UiElementNode mUiRootNode;
- /** Listener to update the root node if the resource framework changes */
- private Runnable mResourceRefreshListener;
/**
* Creates the form editor for resources XML files.
*/
public MenuEditor() {
super();
- initUiRootNode();
}
/**
@@ -66,15 +64,6 @@
// ---- Base Class Overrides ----
- @Override
- public void dispose() {
- if (mResourceRefreshListener != null) {
- EditorsPlugin.getDefault().removeResourceChangedListener(mResourceRefreshListener);
- mResourceRefreshListener = null;
- }
- super.dispose();
- }
-
/**
* Returns whether the "save as" operation is supported by this editor.
* <p/>
@@ -96,7 +85,7 @@
try {
addPage(new MenuTreePage(this));
} catch (PartInitException e) {
- EditorsPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
+ AdtPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
}
}
@@ -121,6 +110,9 @@
*/
@Override
protected void xmlModelChanged(Document xml_doc) {
+ // init the ui root on demand
+ initUiRootNode(false /*force*/);
+
mUiRootNode.setXmlDocument(xml_doc);
if (xml_doc != null) {
ElementDescriptor root_desc = mUiRootNode.getDescriptor();
@@ -139,38 +131,54 @@
// TODO ? startMonitoringMarkers();
} catch (XPathExpressionException e) {
- EditorsPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$
+ AdtPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$
root_desc.getXmlName());
}
}
super.xmlModelChanged(xml_doc);
}
-
- // ---- Local Methods ----
-
/**
* Creates the initial UI Root Node, including the known mandatory elements.
+ * @param force if true, a new UiRootNode is recreated even if it already exists.
*/
- private void initUiRootNode() {
+ @Override
+ protected void initUiRootNode(boolean force) {
// The root UI node is always created, even if there's no corresponding XML node.
- if (mUiRootNode == null) {
- ElementDescriptor desc = MenuDescriptors.getInstance().getDescriptor();
+ if (mUiRootNode == null || force) {
+ Document doc = null;
+ if (mUiRootNode != null) {
+ doc = mUiRootNode.getXmlDocument();
+ }
+
+ // get the target data from the opened file (and its project)
+ AndroidTargetData data = getTargetData();
+
+ ElementDescriptor desc;
+ if (data == null) {
+ desc = new ElementDescriptor("temp", null /*children*/);
+ } else {
+ desc = data.getMenuDescriptors().getDescriptor();
+ }
+
mUiRootNode = desc.createUiNode();
mUiRootNode.setEditor(this);
- // Add a listener to refresh the root node if the resource framework changes
- // by forcing it to parse its own XML
- mResourceRefreshListener = new Runnable() {
- public void run() {
- commitPages(false /* onSave */);
+ onDescriptorsChanged(doc);
+ }
+ }
- mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlNode());
- }
- };
- EditorsPlugin.getDefault().addResourceChangedListener(mResourceRefreshListener);
- mResourceRefreshListener.run();
+ // ---- Local Methods ----
+
+ /**
+ * Reloads the UI manifest node from the XML, and calls the pages to update.
+ */
+ private void onDescriptorsChanged(Document document) {
+ if (document != null) {
+ mUiRootNode.loadFromXmlNode(document);
+ } else {
+ mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlNode());
}
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuSourceViewerConfig.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuSourceViewerConfig.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuSourceViewerConfig.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuSourceViewerConfig.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuTreePage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuTreePage.java
similarity index 94%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuTreePage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuTreePage.java
index 994074e..edbfa5e 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuTreePage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuTreePage.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.menu;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.ui.tree.UiTreeBlock;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
@@ -49,7 +49,7 @@
super.createFormContent(managedForm);
ScrolledForm form = managedForm.getForm();
form.setText("Android Menu");
- form.setImage(EditorsPlugin.getAndroidLogo());
+ form.setImage(AdtPlugin.getAndroidLogo());
UiElementNode rootNode = mEditor.getUiRootNode();
UiTreeBlock block = new UiTreeBlock(mEditor, rootNode,
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/descriptors/MenuDescriptors.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/descriptors/MenuDescriptors.java
similarity index 94%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/descriptors/MenuDescriptors.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/descriptors/MenuDescriptors.java
index 941f736..34c7bb2 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/descriptors/MenuDescriptors.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/descriptors/MenuDescriptors.java
@@ -21,6 +21,7 @@
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
import java.util.ArrayList;
@@ -30,32 +31,22 @@
/**
* Complete description of the menu structure.
*/
-public class MenuDescriptors {
+public final class MenuDescriptors implements IDescriptorProvider {
public static final String MENU_ROOT_ELEMENT = "menu"; //$NON-NLS-1$
-
-
- /** Singleton instance */
- private static MenuDescriptors sThis;
-
/** The root element descriptor. */
private ElementDescriptor mDescriptor = null;
- /** Returns a singleton instance of the {@link MenuDescriptors}. */
- public static synchronized MenuDescriptors getInstance() {
- if (sThis == null) {
- sThis = new MenuDescriptors();
- sThis.updateDescriptors(null);
- }
- return sThis;
- }
-
/** @return the root descriptor. */
public ElementDescriptor getDescriptor() {
return mDescriptor;
}
-
+
+ public ElementDescriptor[] getRootElementDescriptors() {
+ return mDescriptor.getChildren();
+ }
+
/**
* Updates the document descriptor.
* <p/>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesContentAssist.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesContentAssist.java
similarity index 80%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesContentAssist.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesContentAssist.java
index 9fe15ab..c9c8e17 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesContentAssist.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesContentAssist.java
@@ -16,9 +16,8 @@
package com.android.ide.eclipse.editors.resources;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.editors.AndroidContentAssist;
-import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors;
/**
* Content Assist Processor for /res/values and /res/drawable XML files
@@ -29,6 +28,6 @@
* Constructor for ResourcesContentAssist
*/
public ResourcesContentAssist() {
- super(new ElementDescriptor[] { ResourcesDescriptors.RESOURCES_ELEMENT });
+ super(AndroidTargetData.DESCRIPTOR_RESOURCES);
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesEditor.java
similarity index 78%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesEditor.java
index bad5699..46a9112 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesEditor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesEditor.java
@@ -16,9 +16,10 @@
package com.android.ide.eclipse.editors.resources;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidXPathFactory;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
@@ -41,7 +42,7 @@
*/
public class ResourcesEditor extends AndroidEditor {
- public static final String ID = "com.android.ide.eclipse.editors.resources.ResourcesEditor"; //$NON-NLS-1$
+ public static final String ID = AndroidConstants.EDITORS_NAMESPACE + ".resources.ResourcesEditor"; //$NON-NLS-1$
/** Root node of the UI element hierarchy */
private UiElementNode mUiResourcesNode;
@@ -52,7 +53,6 @@
*/
public ResourcesEditor() {
super();
- initUiResourcesNode();
}
/**
@@ -87,8 +87,8 @@
try {
addPage(new ResourcesTreePage(this));
} catch (PartInitException e) {
- EditorsPlugin.log(IStatus.ERROR, "Error creating nested page"); //$NON-NLS-1$
- EditorsPlugin.getDefault().getLog().log(e.getStatus());
+ AdtPlugin.log(IStatus.ERROR, "Error creating nested page"); //$NON-NLS-1$
+ AdtPlugin.getDefault().getLog().log(e.getStatus());
}
}
@@ -113,9 +113,13 @@
*/
@Override
protected void xmlModelChanged(Document xml_doc) {
+ // init the ui root on demand
+ initUiRootNode(false /*force*/);
+
mUiResourcesNode.setXmlDocument(xml_doc);
if (xml_doc != null) {
- ElementDescriptor resources_desc = ResourcesDescriptors.RESOURCES_ELEMENT;
+ ElementDescriptor resources_desc =
+ ResourcesDescriptors.getInstance().getElementDescriptor();
try {
XPath xpath = AndroidXPathFactory.newXPath();
Node node = (Node) xpath.evaluate("/" + resources_desc.getXmlName(), //$NON-NLS-1$
@@ -126,27 +130,35 @@
// Refresh the manifest UI node and all its descendants
mUiResourcesNode.loadFromXmlNode(node);
} catch (XPathExpressionException e) {
- EditorsPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$
+ AdtPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$
resources_desc.getXmlName());
}
}
super.xmlModelChanged(xml_doc);
}
-
- // ---- Local Methods ----
-
/**
* Creates the initial UI Root Node, including the known mandatory elements.
+ * @param force if true, a new UiRootNode is recreated even if it already exists.
*/
- private void initUiResourcesNode() {
+ @Override
+ protected void initUiRootNode(boolean force) {
// The manifest UI node is always created, even if there's no corresponding XML node.
- if (mUiResourcesNode == null) {
- ElementDescriptor resources_desc = ResourcesDescriptors.RESOURCES_ELEMENT;
+ if (mUiResourcesNode == null || force) {
+ ElementDescriptor resources_desc =
+ ResourcesDescriptors.getInstance().getElementDescriptor();
mUiResourcesNode = resources_desc.createUiNode();
mUiResourcesNode.setEditor(this);
+
+ onDescriptorsChanged();
}
}
+ // ---- Local Methods ----
+
+ private void onDescriptorsChanged() {
+ // nothing to be done, as the descriptor are static for now.
+ // FIXME Update when the descriptors are not static
+ }
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesSourceViewerConfig.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesSourceViewerConfig.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesSourceViewerConfig.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesSourceViewerConfig.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesTreePage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesTreePage.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesTreePage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesTreePage.java
index 8cabeca..5c1b0e1 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesTreePage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesTreePage.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.resources;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.resources.manager.ResourceFolder;
import com.android.ide.eclipse.editors.resources.manager.ResourceManager;
import com.android.ide.eclipse.editors.ui.tree.UiTreeBlock;
@@ -72,7 +72,7 @@
form.setText("Android Resources");
}
- form.setImage(EditorsPlugin.getAndroidLogo());
+ form.setImage(AdtPlugin.getAndroidLogo());
UiElementNode resources = mEditor.getUiRootNode();
UiTreeBlock block = new UiTreeBlock(mEditor, resources,
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/CountryCodeQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/CountryCodeQualifier.java
similarity index 98%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/CountryCodeQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/CountryCodeQualifier.java
index 7670fa2..1d01260 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/CountryCodeQualifier.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/CountryCodeQualifier.java
@@ -92,7 +92,7 @@
@Override
public Image getIcon() {
- return IconFactory.getInstance().getIcon("world"); //$NON-NLS-1$
+ return IconFactory.getInstance().getIcon("mcc"); //$NON-NLS-1$
}
@Override
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/FolderConfiguration.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/FolderConfiguration.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/FolderConfiguration.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/FolderConfiguration.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/KeyboardStateQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/KeyboardStateQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/KeyboardStateQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/KeyboardStateQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/LanguageQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/LanguageQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/LanguageQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/LanguageQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/NavigationMethodQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/NavigationMethodQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/NavigationMethodQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/NavigationMethodQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/NetworkCodeQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/NetworkCodeQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/NetworkCodeQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/NetworkCodeQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/PixelDensityQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/PixelDensityQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/PixelDensityQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/PixelDensityQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/RegionQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/RegionQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/RegionQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/RegionQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ResourceQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/ResourceQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ResourceQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/ResourceQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ScreenDimensionQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/ScreenDimensionQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ScreenDimensionQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/ScreenDimensionQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ScreenOrientationQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/ScreenOrientationQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ScreenOrientationQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/ScreenOrientationQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/TextInputMethodQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/TextInputMethodQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/TextInputMethodQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/TextInputMethodQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/TouchScreenQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/TouchScreenQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/TouchScreenQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/TouchScreenQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ColorValueDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ColorValueDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ColorValueDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ColorValueDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ItemElementDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ItemElementDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ItemElementDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ItemElementDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ResourcesDescriptors.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ResourcesDescriptors.java
similarity index 74%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ResourcesDescriptors.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ResourcesDescriptors.java
index 4769cef..1075897 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ResourcesDescriptors.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ResourcesDescriptors.java
@@ -20,16 +20,16 @@
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.descriptors.FlagAttributeDescriptor;
+import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
import com.android.ide.eclipse.editors.descriptors.ListAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.TextValueDescriptor;
/**
- * Complete description of the AndroidManifest.xml structure.
+ * Complete description of the structure for resources XML files (under res/values/)
*/
-public class ResourcesDescriptors {
-
+public class ResourcesDescriptors implements IDescriptorProvider {
// Public attributes names, attributes descriptors and elements descriptors
@@ -38,14 +38,33 @@
public static final String NAME_ATTR = "name"; //$NON-NLS-1$
public static final String TYPE_ATTR = "type"; //$NON-NLS-1$
- /** The {@link ElementDescriptor} for the root Manifest element. */
- public static final ElementDescriptor RESOURCES_ELEMENT;
-
+ private static final ResourcesDescriptors sThis = new ResourcesDescriptors();
- static {
+ /** The {@link ElementDescriptor} for the root Resources element. */
+ public final ElementDescriptor mResourcesElement;
+
+ public static ResourcesDescriptors getInstance() {
+ return sThis;
+ }
+
+ /*
+ * @see com.android.ide.eclipse.editors.descriptors.IDescriptorProvider#getRootElementDescriptors()
+ */
+ public ElementDescriptor[] getRootElementDescriptors() {
+ return new ElementDescriptor[] { mResourcesElement };
+ }
+
+ public ElementDescriptor getDescriptor() {
+ return mResourcesElement;
+ }
+
+ public ElementDescriptor getElementDescriptor() {
+ return mResourcesElement;
+ }
+
+ private ResourcesDescriptors() {
// Common attributes used in many placed
-
// Elements
@@ -189,7 +208,61 @@
},
false /* not mandatory */);
- RESOURCES_ELEMENT = new ElementDescriptor(
+ ElementDescriptor string_array_element = new ElementDescriptor(
+ "string-array", //$NON-NLS-1$
+ "String Array",
+ "An array of strings. Strings are added as underlying item elements to the array.",
+ null, // tooltips
+ new AttributeDescriptor[] {
+ new TextAttributeDescriptor(NAME_ATTR,
+ "Name*",
+ null /* nsUri */,
+ "The mandatory name used in referring to this string array."),
+ },
+ new ElementDescriptor[] {
+ new ElementDescriptor(
+ "item", //$NON-NLS-1$
+ "Item",
+ "A string value to use in this string array.",
+ null, // tooltip
+ new AttributeDescriptor[] {
+ new TextValueDescriptor(
+ "Value*",
+ "A mandatory string.")
+ },
+ null, // no child nodes
+ false /* not mandatory */)
+ },
+ false /* not mandatory */);
+
+ ElementDescriptor integer_array_element = new ElementDescriptor(
+ "integer-array", //$NON-NLS-1$
+ "Integer Array",
+ "An array of integers. Integers are added as underlying item elements to the array.",
+ null, // tooltips
+ new AttributeDescriptor[] {
+ new TextAttributeDescriptor(NAME_ATTR,
+ "Name*",
+ null /* nsUri */,
+ "The mandatory name used in referring to this integer array."),
+ },
+ new ElementDescriptor[] {
+ new ElementDescriptor(
+ "item", //$NON-NLS-1$
+ "Item",
+ "An integer value to use in this integer array.",
+ null, // tooltip
+ new AttributeDescriptor[] {
+ new TextValueDescriptor(
+ "Value*",
+ "A mandatory integer.")
+ },
+ null, // no child nodes
+ false /* not mandatory */)
+ },
+ false /* not mandatory */);
+
+ mResourcesElement = new ElementDescriptor(
ROOT_ELEMENT,
"Resources",
null,
@@ -201,7 +274,9 @@
dimen_element,
drawable_element,
style_element,
- item_element
+ item_element,
+ string_array_element,
+ integer_array_element,
},
true /* mandatory */);
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java
index cc7bec8..845db32 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.resources.explorer;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.resources.manager.ProjectResourceItem;
import com.android.ide.eclipse.editors.resources.manager.ProjectResources;
import com.android.ide.eclipse.editors.resources.manager.ResourceFile;
@@ -73,10 +73,12 @@
public class ResourceExplorerView extends ViewPart implements ISelectionListener,
IResourceEventListener {
+ // Note: keep using the obsolete AndroidConstants.EDITORS_NAMESPACE (which used
+ // to be the Editors Plugin ID) to keep existing preferences functional.
private final static String PREFS_COLUMN_RES =
- AndroidConstants.EDITORS_PLUGIN_ID + "ResourceExplorer.Col1"; //$NON-NLS-1$
+ AndroidConstants.EDITORS_NAMESPACE + "ResourceExplorer.Col1"; //$NON-NLS-1$
private final static String PREFS_COLUMN_2 =
- AndroidConstants.EDITORS_PLUGIN_ID + "ResourceExplorer.Col2"; //$NON-NLS-1$
+ AndroidConstants.EDITORS_NAMESPACE + "ResourceExplorer.Col2"; //$NON-NLS-1$
private Tree mTree;
private TreeViewer mTreeViewer;
@@ -93,7 +95,7 @@
mTree.setHeaderVisible(true);
mTree.setLinesVisible(true);
- final IPreferenceStore store = EditorsPlugin.getDefault().getPreferenceStore();
+ final IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore();
// create 2 columns. The main one with the resources, and an "info" column.
createTreeColumn(mTree, "Resources", SWT.LEFT,
@@ -156,7 +158,7 @@
});
// set up the resource manager to send us resource change notification
- EditorsPlugin.getDefault().getResourceMonitor().addResourceEventListener(this);
+ AdtPlugin.getDefault().getResourceMonitor().addResourceEventListener(this);
}
@Override
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java
similarity index 82%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java
index 366f4fd..455c825 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java
@@ -16,6 +16,7 @@
package com.android.ide.eclipse.editors.resources.manager;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestHelper;
import com.android.ide.eclipse.common.resources.ResourceType;
@@ -124,24 +125,29 @@
ProjectClassLoader loader = new ProjectClassLoader(null /* parentClassLoader */,
project);
- Class<?> clazz = loader.loadClass(className);
-
- if (clazz != null) {
- // create the maps to store the result of the parsing
- Map<String, Map<String, Integer>> resourceValueMap =
- new HashMap<String, Map<String, Integer>>();
- Map<Integer, String[]> genericValueToNameMap =
- new HashMap<Integer, String[]>();
- Map<IntArrayWrapper, String> styleableValueToNameMap =
- new HashMap<IntArrayWrapper, String>();
+ try {
+ Class<?> clazz = loader.loadClass(className);
- // parse the class
- if (parseClass(clazz, genericValueToNameMap, styleableValueToNameMap,
- resourceValueMap)) {
- // now we associate the maps to the project.
- projectResources.setCompiledResources(genericValueToNameMap,
- styleableValueToNameMap, resourceValueMap);
+ if (clazz != null) {
+ // create the maps to store the result of the parsing
+ Map<String, Map<String, Integer>> resourceValueMap =
+ new HashMap<String, Map<String, Integer>>();
+ Map<Integer, String[]> genericValueToNameMap =
+ new HashMap<Integer, String[]>();
+ Map<IntArrayWrapper, String> styleableValueToNameMap =
+ new HashMap<IntArrayWrapper, String>();
+
+ // parse the class
+ if (parseClass(clazz, genericValueToNameMap, styleableValueToNameMap,
+ resourceValueMap)) {
+ // now we associate the maps to the project.
+ projectResources.setCompiledResources(genericValueToNameMap,
+ styleableValueToNameMap, resourceValueMap);
+ }
}
+ } catch (Error e) {
+ // Log this error with the class name we're trying to load and abort.
+ AdtPlugin.log(e, "loadAndParseRClass failed to find class %1$s", className); //$NON-NLS-1$
}
}
} catch (ClassNotFoundException e) {
@@ -155,7 +161,7 @@
* @param genericValueToNameMap
* @param styleableValueToNameMap
* @param resourceValueMap
- * @return
+ * @return True if we managed to parse the R class.
*/
private boolean parseClass(Class<?> rClass, Map<Integer, String[]> genericValueToNameMap,
Map<IntArrayWrapper, String> styleableValueToNameMap, Map<String,
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ConfigurableResourceItem.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ConfigurableResourceItem.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ConfigurableResourceItem.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ConfigurableResourceItem.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/FolderTypeRelationship.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/FolderTypeRelationship.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/FolderTypeRelationship.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/FolderTypeRelationship.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/IdResourceItem.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/IdResourceItem.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/IdResourceItem.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/IdResourceItem.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/IntArrayWrapper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/IntArrayWrapper.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/IntArrayWrapper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/IntArrayWrapper.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/MultiResourceFile.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/MultiResourceFile.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/MultiResourceFile.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/MultiResourceFile.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectClassLoader.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectClassLoader.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectClassLoader.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectClassLoader.java
index 5658224..183af27 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectClassLoader.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectClassLoader.java
@@ -215,12 +215,6 @@
// get the IPath
IPath path = e.getPath();
- // get the file name. if it's the framework jar, we ignore that file.
- // since we now use classpath container, this is here for legacy purpose only.
- if (AndroidConstants.FN_FRAMEWORK_LIBRARY.equals(path.lastSegment())) {
- continue;
- }
-
// check the name ends with .jar
if (AndroidConstants.EXT_JAR.equalsIgnoreCase(path.getFileExtension())) {
boolean local = false;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectResourceItem.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectResourceItem.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectResourceItem.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectResourceItem.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectResources.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectResources.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectResources.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectResources.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/Resource.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/Resource.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/Resource.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/Resource.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFile.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceFile.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFile.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceFile.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolder.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolder.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolder.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolder.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolderType.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolderType.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolderType.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolderType.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceManager.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceManager.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceManager.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceManager.java
index 64942ed..9c5f0fc 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceManager.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceManager.java
@@ -29,6 +29,7 @@
import com.android.ide.eclipse.editors.resources.manager.files.IAbstractFolder;
import com.android.ide.eclipse.editors.resources.manager.files.IFileWrapper;
import com.android.ide.eclipse.editors.resources.manager.files.IFolderWrapper;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
@@ -57,8 +58,6 @@
private final HashMap<IProject, ProjectResources> mMap =
new HashMap<IProject, ProjectResources>();
- private ProjectResources mFrameworkResources = null;
-
/**
* Sets up the resource manager with the global resource monitor.
* @param monitor The global resource monitor
@@ -89,14 +88,6 @@
}
/**
- * Returns the resources of the framework.
- * <p/>This could be <code>null</code> if the parsing failed.
- */
- public ProjectResources getFrameworkResources() {
- return mFrameworkResources;
- }
-
- /**
* Processes folder event.
*/
public void folderChanged(IFolder folder, int kind) {
@@ -277,24 +268,23 @@
}
/**
- * Loads the framework resources.
+ * Loads and returns the resources for a given {@link IAndroidTarget}
* @param osFilePath the path to the folder containing all the versions of the framework
* resources
*/
- public void loadFrameworkResources(String osResourcesPath) {
- // for now only load the default framework resources
- osResourcesPath += AndroidConstants.FD_DEFAULT_RES;
+ public ProjectResources loadFrameworkResources(IAndroidTarget androidTarget) {
+ String osResourcesPath = androidTarget.getPath(IAndroidTarget.RESOURCES);
File frameworkRes = new File(osResourcesPath);
if (frameworkRes.isDirectory()) {
- mFrameworkResources = new ProjectResources(true /* isFrameworkRepository */);
+ ProjectResources resources = new ProjectResources(true /* isFrameworkRepository */);
try {
File[] files = frameworkRes.listFiles();
for (File file : files) {
if (file.isDirectory()) {
ResourceFolder resFolder = processFolder(new FolderWrapper(file),
- mFrameworkResources);
+ resources);
if (resFolder != null) {
// now we process the content of the folder
@@ -311,13 +301,17 @@
}
// now that we have loaded the files, we need to force load the resources from them
- mFrameworkResources.loadAll();
+ resources.loadAll();
+
+ return resources;
} catch (IOException e) {
// since we test that folders are folders, and files are files, this shouldn't
// happen. We can ignore it.
}
}
+
+ return null;
}
/**
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java
index 45a020c..dc0f505 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java
@@ -257,6 +257,20 @@
mFileListeners.add(bundle);
}
+
+ /**
+ * Removes an existing file listener.
+ * @param listener the listener to remove.
+ */
+ public synchronized void removeFileListener(IFileListener listener) {
+ for (int i = 0 ; i < mFileListeners.size() ; i++) {
+ FileListenerBundle bundle = mFileListeners.get(i);
+ if (bundle.listener == listener) {
+ mFileListeners.remove(i);
+ return;
+ }
+ }
+ }
/**
* Adds a folder listener.
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/SingleResourceFile.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/SingleResourceFile.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/SingleResourceFile.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/SingleResourceFile.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/FileWrapper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/FileWrapper.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/FileWrapper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/FileWrapper.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/FolderWrapper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/FolderWrapper.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/FolderWrapper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/FolderWrapper.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFile.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFile.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFile.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFile.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFolder.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFolder.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFolder.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFolder.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractResource.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractResource.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractResource.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractResource.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IFileWrapper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IFileWrapper.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IFileWrapper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IFileWrapper.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IFolderWrapper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IFolderWrapper.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IFolderWrapper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IFolderWrapper.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/uimodel/UiColorValueNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/uimodel/UiColorValueNode.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/uimodel/UiColorValueNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/uimodel/UiColorValueNode.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/uimodel/UiItemElementNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/uimodel/UiItemElementNode.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/uimodel/UiItemElementNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/uimodel/UiItemElementNode.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/EditableDialogCellEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/EditableDialogCellEditor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/EditableDialogCellEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/EditableDialogCellEditor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ErrorImageComposite.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/ErrorImageComposite.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ErrorImageComposite.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/ErrorImageComposite.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/FlagValueCellEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/FlagValueCellEditor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/FlagValueCellEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/FlagValueCellEditor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ListValueCellEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/ListValueCellEditor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ListValueCellEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/ListValueCellEditor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ResourceValueCellEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/ResourceValueCellEditor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ResourceValueCellEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/ResourceValueCellEditor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/SectionHelper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/SectionHelper.java
similarity index 98%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/SectionHelper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/SectionHelper.java
index 7942024..409e92f 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/SectionHelper.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/SectionHelper.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.ui;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import org.eclipse.jface.text.DefaultInformationControl;
import org.eclipse.swt.events.MouseEvent;
@@ -173,7 +173,7 @@
reflow.setAccessible(true);
reflow.invoke(section);
} catch (Exception e) {
- EditorsPlugin.log(e, "Error when invoking Section.reflow");
+ AdtPlugin.log(e, "Error when invoking Section.reflow");
}
section.layout(true /* changed */, true /* all */);
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/TextValueCellEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/TextValueCellEditor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/TextValueCellEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/TextValueCellEditor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/UiElementPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/UiElementPart.java
similarity index 97%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/UiElementPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/UiElementPart.java
index 69adebd..66773bd 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/UiElementPart.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/UiElementPart.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.ui;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.ide.eclipse.editors.manifest.ManifestEditor;
@@ -60,7 +60,7 @@
if (uiElementNode == null) {
// This is serious and should never happen. Instead of crashing, simply abort.
// There will be no UI, which will prevent further damage.
- EditorsPlugin.log(IStatus.ERROR, "Missing node to edit!"); //$NON-NLS-1$
+ AdtPlugin.log(IStatus.ERROR, "Missing node to edit!"); //$NON-NLS-1$
return;
}
}
@@ -222,7 +222,7 @@
} else {
// The XML has an extra attribute which wasn't declared in
// AndroidManifestDescriptors. This is not a problem, we just ignore it.
- EditorsPlugin.log(IStatus.WARNING,
+ AdtPlugin.log(IStatus.WARNING,
"Attribute %1$s not declared in node %2$s, ignored.", //$NON-NLS-1$
attr_desc.getXmlLocalName(),
uiNode.getDescriptor().getXmlName());
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java
new file mode 100644
index 0000000..2aad217
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.editors.ui.tree;
+
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.editors.AndroidEditor;
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+
+import org.apache.xml.serialize.Method;
+import org.apache.xml.serialize.OutputFormat;
+import org.apache.xml.serialize.XMLSerializer;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.xml.core.internal.document.NodeContainer;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * Provides Cut and Copy actions for the tree nodes.
+ */
+public class CopyCutAction extends Action {
+ private List<UiElementNode> mUiNodes;
+ private boolean mPerformCut;
+ private final AndroidEditor mEditor;
+ private final Clipboard mClipboard;
+ private final ICommitXml mXmlCommit;
+
+ /**
+ * Creates a new Copy or Cut action.
+ *
+ * @param selected The UI node to cut or copy. It *must* have a non-null XML node.
+ * @param perform_cut True if the operation is cut, false if it is copy.
+ */
+ public CopyCutAction(AndroidEditor editor, Clipboard clipboard, ICommitXml xmlCommit,
+ UiElementNode selected, boolean perform_cut) {
+ this(editor, clipboard, xmlCommit, toList(selected), perform_cut);
+ }
+
+ /**
+ * Creates a new Copy or Cut action.
+ *
+ * @param selected The UI nodes to cut or copy. They *must* have a non-null XML node.
+ * The list becomes owned by the {@link CopyCutAction}.
+ * @param perform_cut True if the operation is cut, false if it is copy.
+ */
+ public CopyCutAction(AndroidEditor editor, Clipboard clipboard, ICommitXml xmlCommit,
+ List<UiElementNode> selected, boolean perform_cut) {
+ super(perform_cut ? "Cut" : "Copy");
+ mEditor = editor;
+ mClipboard = clipboard;
+ mXmlCommit = xmlCommit;
+
+ ISharedImages images = PlatformUI.getWorkbench().getSharedImages();
+ if (perform_cut) {
+ setImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT));
+ setHoverImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT));
+ setDisabledImageDescriptor(
+ images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT_DISABLED));
+ } else {
+ setImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
+ setHoverImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
+ setDisabledImageDescriptor(
+ images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY_DISABLED));
+ }
+
+ mUiNodes = selected;
+ mPerformCut = perform_cut;
+ }
+
+ /**
+ * Performs the cut or copy action.
+ * First an XML serializer is used to turn the existing XML node into a valid
+ * XML fragment, which is added as text to the clipboard.
+ */
+ @Override
+ public void run() {
+ super.run();
+ if (mUiNodes == null || mUiNodes.size() < 1) {
+ return;
+ }
+
+ // Commit the current pages first, to make sure the XML is in sync.
+ // Committing may change the XML structure.
+ if (mXmlCommit != null) {
+ mXmlCommit.commitPendingXmlChanges();
+ }
+
+ StringBuilder allText = new StringBuilder();
+ ArrayList<UiElementNode> nodesToCut = mPerformCut ? new ArrayList<UiElementNode>() : null;
+
+ for (UiElementNode uiNode : mUiNodes) {
+ try {
+ Node xml_node = uiNode.getXmlNode();
+ if (xml_node == null) {
+ return;
+ }
+
+ String data = getXmlTextFromEditor(xml_node);
+
+ // In the unlikely event that IStructuredDocument failed to extract the text
+ // directly from the editor, try to fall back on a direct XML serialization
+ // of the XML node. This uses the generic Node interface with no SSE tricks.
+ if (data == null) {
+ data = getXmlTextFromSerialization(xml_node);
+ }
+
+ if (data != null) {
+ allText.append(data);
+ if (mPerformCut) {
+ // only remove notes to cut if we actually got some XML text from them
+ nodesToCut.add(uiNode);
+ }
+ }
+
+ } catch (Exception e) {
+ AdtPlugin.log(e, "CopyCutAction failed for UI node %1$s", //$NON-NLS-1$
+ uiNode.getBreadcrumbTrailDescription(true));
+ }
+ } // for uiNode
+
+ if (allText != null && allText.length() > 0) {
+ mClipboard.setContents(
+ new Object[] { allText.toString() },
+ new Transfer[] { TextTransfer.getInstance() });
+ if (mPerformCut) {
+ for (UiElementNode uiNode : nodesToCut) {
+ uiNode.deleteXmlNode();
+ }
+ }
+ }
+ }
+
+ /** Get the data directly from the editor. */
+ private String getXmlTextFromEditor(Node xml_node) {
+ String data = null;
+ IStructuredModel model = mEditor.getModelForRead();
+ try {
+ IStructuredDocument sse_doc = mEditor.getStructuredDocument();
+ if (xml_node instanceof NodeContainer) {
+ // The easy way to get the source of an SSE XML node.
+ data = ((NodeContainer) xml_node).getSource();
+ } else if (xml_node instanceof IndexedRegion && sse_doc != null) {
+ // Try harder.
+ IndexedRegion region = (IndexedRegion) xml_node;
+ int start = region.getStartOffset();
+ int end = region.getEndOffset();
+
+ if (end > start) {
+ data = sse_doc.get(start, end - start);
+ }
+ }
+ } catch (BadLocationException e) {
+ // the region offset was invalid. ignore.
+ } finally {
+ model.releaseFromRead();
+ }
+ return data;
+ }
+
+ /**
+ * Direct XML serialization of the XML node.
+ * <p/>
+ * This uses the generic Node interface with no SSE tricks. It's however slower
+ * and doesn't respect formatting (since serialization is involved instead of reading
+ * the actual text buffer.)
+ */
+ private String getXmlTextFromSerialization(Node xml_node) throws IOException {
+ String data;
+ StringWriter sw = new StringWriter();
+ XMLSerializer serializer = new XMLSerializer(sw,
+ new OutputFormat(Method.XML,
+ OutputFormat.Defaults.Encoding /* utf-8 */,
+ true /* indent */));
+ // Serialize will throw an IOException if it fails.
+ serializer.serialize((Element) xml_node);
+ data = sw.toString();
+ return data;
+ }
+
+ /**
+ * Static helper class to wrap on node into a list for the constructors.
+ */
+ private static ArrayList<UiElementNode> toList(UiElementNode selected) {
+ ArrayList<UiElementNode> list = null;
+ if (selected != null) {
+ list = new ArrayList<UiElementNode>(1);
+ list.add(selected);
+ }
+ return list;
+ }
+}
+
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/ICommitXml.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/ICommitXml.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/ICommitXml.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/ICommitXml.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java
similarity index 97%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java
index 00e44ab..772fb52 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java
@@ -16,6 +16,7 @@
package com.android.ide.eclipse.editors.ui.tree;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor;
@@ -90,19 +91,19 @@
public IStatus validate(Object[] selection) {
if (selection.length == 1 && selection[0] instanceof ViewElementDescriptor) {
return new Status(IStatus.OK, // severity
- AndroidConstants.EDITORS_PLUGIN_ID, //plugin id
+ AdtPlugin.PLUGIN_ID, //plugin id
IStatus.OK, // code
((ViewElementDescriptor) selection[0]).getCanonicalClassName(), //msg
null); // exception
} else if (selection.length == 1 && selection[0] instanceof ElementDescriptor) {
return new Status(IStatus.OK, // severity
- AndroidConstants.EDITORS_PLUGIN_ID, //plugin id
+ AdtPlugin.PLUGIN_ID, //plugin id
IStatus.OK, // code
"", //$NON-NLS-1$ // msg
null); // exception
} else {
return new Status(IStatus.ERROR, // severity
- AndroidConstants.EDITORS_PLUGIN_ID, //plugin id
+ AdtPlugin.PLUGIN_ID, //plugin id
IStatus.ERROR, // code
"Invalid selection", // msg, translatable
null); // exception
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/PasteAction.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/PasteAction.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/PasteAction.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/PasteAction.java
index 68580b0..8bb4ad2 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/PasteAction.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/PasteAction.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.ui.tree;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
@@ -113,7 +113,7 @@
}
} catch (BadLocationException e) {
- EditorsPlugin.log(e, "ParseAction failed for UI Node %2$s, content '%1$s'", //$NON-NLS-1$
+ AdtPlugin.log(e, "ParseAction failed for UI Node %2$s, content '%1$s'", //$NON-NLS-1$
mUiNode.getBreadcrumbTrailDescription(true), data);
} finally {
model.releaseFromEdit();
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java
new file mode 100644
index 0000000..21180b1
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java
@@ -0,0 +1,385 @@
+/*
+ * 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.ide.eclipse.editors.ui.tree;
+
+import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
+import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.swt.widgets.Shell;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import java.util.List;
+
+/**
+ * Performs basic actions on an XML tree: add node, remove node, move up/down.
+ */
+public abstract class UiActions implements ICommitXml {
+
+ public UiActions() {
+ }
+
+ //---------------------
+ // Actual implementations must override these to provide specific hooks
+
+ /** Returns the UiDocumentNode for the current model. */
+ abstract protected UiElementNode getRootNode();
+
+ /** Commits pending data before the XML model is modified. */
+ abstract public void commitPendingXmlChanges();
+
+ /**
+ * Utility method to select an outline item based on its model node
+ *
+ * @param uiNode The node to select. Can be null (in which case nothing should happen)
+ */
+ abstract protected void selectUiNode(UiElementNode uiNode);
+
+ //---------------------
+
+ /**
+ * Called when the "Add..." button next to the tree view is selected.
+ * <p/>
+ * This simplified version of doAdd does not support descriptor filters and creates
+ * a new {@link UiModelTreeLabelProvider} for each call.
+ */
+ public void doAdd(UiElementNode uiNode, Shell shell) {
+ doAdd(uiNode, null /* descriptorFilters */, shell, new UiModelTreeLabelProvider());
+ }
+
+ /**
+ * Called when the "Add..." button next to the tree view is selected.
+ *
+ * Displays a selection dialog that lets the user select which kind of node
+ * to create, depending on the current selection.
+ */
+ public void doAdd(UiElementNode uiNode,
+ ElementDescriptor[] descriptorFilters,
+ Shell shell, ILabelProvider labelProvider) {
+ // If the root node is a document with already a root, use it as the root node
+ UiElementNode rootNode = getRootNode();
+ if (rootNode instanceof UiDocumentNode && rootNode.getUiChildren().size() > 0) {
+ rootNode = rootNode.getUiChildren().get(0);
+ }
+
+ NewItemSelectionDialog dlg = new NewItemSelectionDialog(
+ shell,
+ labelProvider,
+ descriptorFilters,
+ uiNode, rootNode);
+ dlg.open();
+ Object[] results = dlg.getResult();
+ if (results != null && results.length > 0) {
+ addElement(dlg.getChosenRootNode(), null, (ElementDescriptor) results[0],
+ true /*updateLayout*/);
+ }
+ }
+
+ /**
+ * Adds a new XML element based on the {@link ElementDescriptor} to the given parent
+ * {@link UiElementNode}, and then select it.
+ * <p/>
+ * If the parent is a document root which already contains a root element, the inner
+ * root element is used as the actual parent. This ensure you can't create a broken
+ * XML file with more than one root element.
+ * <p/>
+ * If a sibling is given and that sibling has the same parent, the new node is added
+ * right after that sibling. Otherwise the new node is added at the end of the parent
+ * child list.
+ *
+ * @param uiParent An existing UI node or null to add to the tree root
+ * @param uiSibling An existing UI node before which to insert the new node. Can be null.
+ * @param descriptor The descriptor of the element to add
+ * @param updateLayout True if layout attributes should be set
+ * @return The new {@link UiElementNode} or null.
+ */
+ public UiElementNode addElement(UiElementNode uiParent,
+ UiElementNode uiSibling,
+ ElementDescriptor descriptor,
+ boolean updateLayout) {
+ if (uiParent instanceof UiDocumentNode && uiParent.getUiChildren().size() > 0) {
+ uiParent = uiParent.getUiChildren().get(0);
+ }
+ if (uiSibling != null && uiSibling.getUiParent() != uiParent) {
+ uiSibling = null;
+ }
+
+ UiElementNode uiNew = addNewTreeElement(uiParent, uiSibling, descriptor, updateLayout);
+ selectUiNode(uiNew);
+
+ return uiNew;
+ }
+
+ /**
+ * Called when the "Remove" button is selected.
+ *
+ * If the tree has a selection, remove it.
+ * This simply deletes the XML node attached to the UI node: when the XML model fires the
+ * update event, the tree will get refreshed.
+ */
+ public void doRemove(final List<UiElementNode> nodes, Shell shell) {
+
+ if (nodes == null || nodes.size() == 0) {
+ return;
+ }
+
+ final int len = nodes.size();
+
+ StringBuilder sb = new StringBuilder();
+ for (UiElementNode node : nodes) {
+ sb.append("\n- "); //$NON-NLS-1$
+ sb.append(node.getBreadcrumbTrailDescription(false /* include_root */));
+ }
+
+ if (MessageDialog.openQuestion(shell,
+ len > 1 ? "Remove elements from Android XML" // title
+ : "Remove element from Android XML",
+ String.format("Do you really want to remove %1$s?", sb.toString()))) {
+ commitPendingXmlChanges();
+ getRootNode().getEditor().editXmlModel(new Runnable() {
+ public void run() {
+ UiElementNode previous = null;
+ UiElementNode parent = null;
+
+ for (int i = len - 1; i >= 0; i--) {
+ UiElementNode node = nodes.get(i);
+ previous = node.getUiPreviousSibling();
+ parent = node.getUiParent();
+
+ // delete node
+ node.deleteXmlNode();
+ }
+
+ // try to select the last previous sibling or the last parent
+ if (previous != null) {
+ selectUiNode(previous);
+ } else if (parent != null) {
+ selectUiNode(parent);
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * Called when the "Up" button is selected.
+ * <p/>
+ * If the tree has a selection, move it up, either in the child list or as the last child
+ * of the previous parent.
+ */
+ public void doUp(final List<UiElementNode> nodes) {
+ if (nodes == null || nodes.size() < 1) {
+ return;
+ }
+
+ final Node[] select_xml_node = { null };
+ UiElementNode last_node = null;
+ UiElementNode search_root = null;
+
+ for (int i = 0; i < nodes.size(); i++) {
+ final UiElementNode node = last_node = nodes.get(i);
+
+ // the node will move either up to its parent or grand-parent
+ search_root = node.getUiParent();
+ if (search_root != null && search_root.getUiParent() != null) {
+ search_root = search_root.getUiParent();
+ }
+
+ commitPendingXmlChanges();
+ getRootNode().getEditor().editXmlModel(new Runnable() {
+ public void run() {
+ Node xml_node = node.getXmlNode();
+ if (xml_node != null) {
+ Node xml_parent = xml_node.getParentNode();
+ if (xml_parent != null) {
+ UiElementNode ui_prev = node.getUiPreviousSibling();
+ if (ui_prev != null && ui_prev.getXmlNode() != null) {
+ // This node is not the first one of the parent, so it can be
+ // removed and then inserted before its previous sibling.
+ // If the previous sibling can have children, though, then it
+ // is inserted at the end of the children list.
+ Node xml_prev = ui_prev.getXmlNode();
+ if (ui_prev.getDescriptor().hasChildren()) {
+ xml_prev.appendChild(xml_parent.removeChild(xml_node));
+ select_xml_node[0] = xml_node;
+ } else {
+ xml_parent.insertBefore(
+ xml_parent.removeChild(xml_node),
+ xml_prev);
+ select_xml_node[0] = xml_node;
+ }
+ } else if (!(xml_parent instanceof Document) &&
+ xml_parent.getParentNode() != null &&
+ !(xml_parent.getParentNode() instanceof Document)) {
+ // If the node is the first one of the child list of its
+ // parent, move it up in the hierarchy as previous sibling
+ // to the parent. This is only possible if the parent of the
+ // parent is not a document.
+ Node grand_parent = xml_parent.getParentNode();
+ grand_parent.insertBefore(xml_parent.removeChild(xml_node),
+ xml_parent);
+ select_xml_node[0] = xml_node;
+ }
+ }
+ }
+ }
+ });
+ }
+
+ if (select_xml_node[0] == null) {
+ // The XML node has not been moved, we can just select the same UI node
+ selectUiNode(last_node);
+ } else {
+ // The XML node has moved. At this point the UI model has been reloaded
+ // and the XML node has been affected to a new UI node. Find that new UI
+ // node and select it.
+ if (search_root == null) {
+ search_root = last_node.getUiRoot();
+ }
+ if (search_root != null) {
+ selectUiNode(search_root.findXmlNode(select_xml_node[0]));
+ }
+ }
+ }
+
+ /**
+ * Called when the "Down" button is selected.
+ *
+ * If the tree has a selection, move it down, either in the same child list or as the
+ * first child of the next parent.
+ */
+ public void doDown(final List<UiElementNode> nodes) {
+ if (nodes == null || nodes.size() < 1) {
+ return;
+ }
+
+ final Node[] select_xml_node = { null };
+ UiElementNode last_node = null;
+ UiElementNode search_root = null;
+
+ for (int i = nodes.size() - 1; i >= 0; i--) {
+ final UiElementNode node = last_node = nodes.get(i);
+ // the node will move either down to its parent or grand-parent
+ search_root = node.getUiParent();
+ if (search_root != null && search_root.getUiParent() != null) {
+ search_root = search_root.getUiParent();
+ }
+
+ commitPendingXmlChanges();
+ getRootNode().getEditor().editXmlModel(new Runnable() {
+ public void run() {
+ Node xml_node = node.getXmlNode();
+ if (xml_node != null) {
+ Node xml_parent = xml_node.getParentNode();
+ if (xml_parent != null) {
+ UiElementNode uiNext = node.getUiNextSibling();
+ if (uiNext != null && uiNext.getXmlNode() != null) {
+ // This node is not the last one of the parent, so it can be
+ // removed and then inserted after its next sibling.
+ // If the next sibling is a node that can have children, though,
+ // then the node is inserted as the first child.
+ Node xml_next = uiNext.getXmlNode();
+ if (uiNext.getDescriptor().hasChildren()) {
+ // Note: insertBefore works as append if the ref node is
+ // null, i.e. when the node doesn't have children yet.
+ xml_next.insertBefore(xml_parent.removeChild(xml_node),
+ xml_next.getFirstChild());
+ select_xml_node[0] = xml_node;
+ } else {
+ // Insert "before after next" ;-)
+ xml_parent.insertBefore(xml_parent.removeChild(xml_node),
+ xml_next.getNextSibling());
+ select_xml_node[0] = xml_node;
+ }
+ } else if (!(xml_parent instanceof Document) &&
+ xml_parent.getParentNode() != null &&
+ !(xml_parent.getParentNode() instanceof Document)) {
+ // This node is the last node of its parent.
+ // If neither the parent nor the grandparent is a document,
+ // then the node can be insert right after the parent.
+ Node grand_parent = xml_parent.getParentNode();
+ grand_parent.insertBefore(xml_parent.removeChild(xml_node),
+ xml_parent.getNextSibling());
+ select_xml_node[0] = xml_node;
+ }
+ }
+ }
+ }
+ });
+ }
+
+ if (select_xml_node[0] == null) {
+ // The XML node has not been moved, we can just select the same UI node
+ selectUiNode(last_node);
+ } else {
+ // The XML node has moved. At this point the UI model has been reloaded
+ // and the XML node has been affected to a new UI node. Find that new UI
+ // node and select it.
+ if (search_root == null) {
+ search_root = last_node.getUiRoot();
+ }
+ if (search_root != null) {
+ selectUiNode(search_root.findXmlNode(select_xml_node[0]));
+ }
+ }
+ }
+
+ //---------------------
+
+ /**
+ * Adds a new element of the given descriptor's type to the given UI parent node.
+ *
+ * This actually creates the corresponding XML node in the XML model, which in turn
+ * will refresh the current tree view.
+ *
+ * @param uiParent An existing UI node or null to add to the tree root
+ * @param uiSibling An existing UI node to insert right before. Can be null.
+ * @param descriptor The descriptor of the element to add
+ * @param updateLayout True if layout attributes should be set
+ * @return The {@link UiElementNode} that has been added to the UI tree.
+ */
+ private UiElementNode addNewTreeElement(UiElementNode uiParent,
+ final UiElementNode uiSibling,
+ ElementDescriptor descriptor,
+ final boolean updateLayout) {
+ commitPendingXmlChanges();
+
+ int index = 0;
+ for (UiElementNode uiChild : uiParent.getUiChildren()) {
+ if (uiChild == uiSibling) {
+ break;
+ }
+ index++;
+ }
+
+ final UiElementNode uiNew = uiParent.insertNewUiChild(index, descriptor);
+ UiElementNode rootNode = getRootNode();
+
+ rootNode.getEditor().editXmlModel(new Runnable() {
+ public void run() {
+ DescriptorsUtils.setDefaultLayoutAttributes(uiNew, updateLayout);
+ Node xmlNode = uiNew.createXmlNode();
+ }
+ });
+ return uiNew;
+ }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiElementDetail.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiElementDetail.java
similarity index 95%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiElementDetail.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiElementDetail.java
index 010e30e..15c67c3 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiElementDetail.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiElementDetail.java
@@ -16,14 +16,14 @@
package com.android.ide.eclipse.editors.ui.tree;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor;
+import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.ide.eclipse.editors.ui.SectionHelper;
import com.android.ide.eclipse.editors.ui.SectionHelper.ManifestSectionPart;
import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener;
@@ -130,7 +130,7 @@
// Finally reset the dirty flag if everything was saved properly
mIsDirty = false;
} catch (Exception e) {
- EditorsPlugin.log(e, "Detail node failed to commit XML attribute!"); //$NON-NLS-1$
+ AdtPlugin.log(e, "Detail node failed to commit XML attribute!"); //$NON-NLS-1$
} finally {
// Notify the model we're done modifying it. This must *always* be executed.
model.changedModel();
@@ -260,9 +260,15 @@
mCurrentUiElementNode = ui_node;
if (elem_desc.getTooltip() != null) {
- String tooltip = DescriptorsUtils.formatFormText(elem_desc.getTooltip(),
- elem_desc,
- FrameworkResourceManager.getInstance().getDocumentationBaseUrl());
+ String tooltip;
+ if (Sdk.getCurrent() != null &&
+ Sdk.getCurrent().getDocumentationBaseUrl() != null) {
+ tooltip = DescriptorsUtils.formatFormText(elem_desc.getTooltip(),
+ elem_desc,
+ Sdk.getCurrent().getDocumentationBaseUrl());
+ } else {
+ tooltip = elem_desc.getTooltip();
+ }
try {
FormText text = SectionHelper.createFormText(masterTable, toolkit,
@@ -275,7 +281,7 @@
} catch(Exception e) {
// The FormText parser is really really basic and will fail as soon as the
// HTML javadoc is ever so slightly malformatted.
- EditorsPlugin.log(e,
+ AdtPlugin.log(e,
"Malformed javadoc, rejected by FormText for node %1$s: '%2$s'", //$NON-NLS-1$
ui_node.getDescriptor().getXmlName(),
tooltip);
@@ -320,7 +326,7 @@
} else {
// The XML has an extra unknown attribute.
// This is not expected to happen so it is ignored.
- EditorsPlugin.log(IStatus.INFO,
+ AdtPlugin.log(IStatus.INFO,
"Attribute %1$s not declared in node %2$s, ignored.", //$NON-NLS-1$
attr_desc.getXmlLocalName(),
ui_node.getDescriptor().getXmlName());
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeContentProvider.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeContentProvider.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeContentProvider.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeContentProvider.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeLabelProvider.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeLabelProvider.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeLabelProvider.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeLabelProvider.java
index ff5f24c..273a30b 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeLabelProvider.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeLabelProvider.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.ui.tree;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.ui.ErrorImageComposite;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
@@ -62,7 +62,7 @@
}
}
}
- return EditorsPlugin.getAndroidLogo();
+ return AdtPlugin.getAndroidLogo();
}
/**
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiTreeBlock.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiTreeBlock.java
similarity index 74%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiTreeBlock.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiTreeBlock.java
index 7e7bd68..e3255d9 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiTreeBlock.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiTreeBlock.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.ui.tree;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.IconFactory;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.ui.SectionHelper;
@@ -42,6 +42,7 @@
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.events.DisposeEvent;
@@ -64,6 +65,8 @@
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
+import java.util.ArrayList;
+import java.util.Iterator;
import java.util.LinkedList;
/**
@@ -117,9 +120,15 @@
private IUiUpdateListener mUiRefreshListener;
/** Listener to enable/disable the UI based on the application node's presence */
private IUiUpdateListener mUiEnableListener;
-
+ /** An adapter/wrapper to use the add/remove/up/down tree edit actions. */
private UiTreeActions mUiTreeActions;
-
+ /**
+ * True if the root node can be created on-demand (i.e. as needed as
+ * soon as children exist). False if an external entity controls the existence of the
+ * root node. In practise, this is false for the manifest application page (the actual
+ * "application" node is managed by the ApplicationToggle part) whereas it is true
+ * for all other tree pages.
+ */
private final boolean mAutoCreateRoot;
@@ -192,10 +201,24 @@
private void createSectionActions(Section section, FormToolkit toolkit) {
ToolBarManager manager = new ToolBarManager(SWT.FLAT);
+ manager.removeAll();
+
ToolBar toolbar = manager.createControl(section);
section.setTextClient(toolbar);
+ ElementDescriptor[] descs = mDescriptorFilters;
+ if (descs == null && mUiRootNode != null) {
+ descs = mUiRootNode.getDescriptor().getChildren();
+ }
+
+ if (descs != null && descs.length > 1) {
+ for (ElementDescriptor desc : descs) {
+ manager.add(new DescriptorFilterAction(desc));
+ }
+ }
+
manager.add(new TreeSortAction());
+
manager.update(true /*force*/);
}
@@ -207,7 +230,7 @@
final IManagedForm managedForm) {
// Note: we *could* use a FilteredTree instead of the Tree+TreeViewer here.
// However the class must be adapted to create an adapted toolkit tree.
- final Tree tree = toolkit.createTree(grid, SWT.SINGLE);
+ final Tree tree = toolkit.createTree(grid, SWT.MULTI);
GridData gd = new GridData(GridData.FILL_BOTH);
gd.widthHint = AndroidEditor.TEXT_WIDTH_HINT;
gd.heightHint = TREE_HEIGHT_HINT;
@@ -283,7 +306,7 @@
changeRootAndDescriptors(mUiRootNode, mDescriptorFilters, false /* refresh */);
// Listen on resource framework changes to refresh the tree
- EditorsPlugin.getDefault().addResourceChangedListener(resourceRefreshListener);
+ AdtPlugin.getDefault().addResourceChangedListener(resourceRefreshListener);
// Remove listeners when the tree widget gets disposed.
tree.addDisposeListener(new DisposeListener() {
@@ -295,7 +318,7 @@
node.removeUpdateListener(mUiRefreshListener);
mUiRootNode.removeUpdateListener(mUiEnableListener);
- EditorsPlugin.getDefault().removeResourceChangedListener(resourceRefreshListener);
+ AdtPlugin.getDefault().removeResourceChangedListener(resourceRefreshListener);
if (mClipboard != null) {
mClipboard.dispose();
mClipboard = null;
@@ -350,6 +373,8 @@
if (forceRefresh) {
mTreeViewer.refresh();
}
+
+ createSectionActions(mMasterPart.getSection(), mManagedForm.getToolkit());
}
/**
@@ -426,13 +451,9 @@
public void menuAboutToShow(IMenuManager manager) {
ISelection selection = mTreeViewer.getSelection();
if (!selection.isEmpty() && selection instanceof ITreeSelection) {
- ITreeSelection tree_selection = (ITreeSelection) selection;
- Object first = tree_selection.getFirstElement();
- if (first != null && first instanceof UiElementNode) {
- UiElementNode ui_node = (UiElementNode) first;
- doCreateMenuAction(manager, ui_node);
- return;
- }
+ ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection);
+ doCreateMenuAction(manager, selected);
+ return;
}
doCreateMenuAction(manager, null /* ui_node */);
}
@@ -446,63 +467,78 @@
* the tree view.
*
* @param manager The context menu manager
- * @param ui_node The UI node selected in the tree. Can be null, in which case the root
+ * @param selected The UI nodes selected in the tree. Can be null, in which case the root
* is to be modified.
*/
- private void doCreateMenuAction(IMenuManager manager, UiElementNode ui_node) {
- Action action;
-
- if (ui_node != null && ui_node.getXmlNode() != null) {
- manager.add(new CopyCutAction(getEditor(), getClipboard(),
- this, ui_node, true /* cut */));
- manager.add(new CopyCutAction(getEditor(), getClipboard(),
- this, ui_node, false /* cut */));
- // Paste is not valid if it would add a second element on a terminal element
- // which parent is a document -- an XML document can only have one child. This
- // means paste is valid if the current UI node can have children or if the parent
- // is not a document.
- if (mUiRootNode.getDescriptor().hasChildren() ||
- !(mUiRootNode.getUiParent() instanceof UiDocumentNode)) {
- manager.add(new PasteAction(getEditor(), getClipboard(), ui_node));
+ private void doCreateMenuAction(IMenuManager manager, ArrayList<UiElementNode> selected) {
+ if (selected != null) {
+ boolean hasXml = false;
+ for (UiElementNode uiNode : selected) {
+ if (uiNode.getXmlNode() != null) {
+ hasXml = true;
+ break;
+ }
}
- manager.add(new Separator());
+
+ if (hasXml) {
+ manager.add(new CopyCutAction(getEditor(), getClipboard(),
+ null, selected, true /* cut */));
+ manager.add(new CopyCutAction(getEditor(), getClipboard(),
+ null, selected, false /* cut */));
+
+ // Can't paste with more than one element selected (the selection is the target)
+ if (selected.size() <= 1) {
+ // Paste is not valid if it would add a second element on a terminal element
+ // which parent is a document -- an XML document can only have one child. This
+ // means paste is valid if the current UI node can have children or if the
+ // parent is not a document.
+ UiElementNode ui_root = selected.get(0).getUiRoot();
+ if (ui_root.getDescriptor().hasChildren() ||
+ !(ui_root.getUiParent() instanceof UiDocumentNode)) {
+ manager.add(new PasteAction(getEditor(), getClipboard(), selected.get(0)));
+ }
+ }
+ manager.add(new Separator());
+ }
}
// Append "add" and "remove" actions. They do the same thing as the add/remove
// buttons on the side.
-
- manager.add(new Action("Add...", EditorsPlugin.getAndroidLogoDesc()) {
- @Override
- public void run() {
- super.run();
- doTreeAdd();
- }
- });
-
- if (ui_node != null) {
- manager.add(new Action("Remove", EditorsPlugin.getAndroidLogoDesc()) {
+ Action action;
+ IconFactory factory = IconFactory.getInstance();
+
+ // "Add" makes sense only if there's 0 or 1 item selected since the
+ // one selected item becomes the target.
+ if (selected == null || selected.size() <= 1) {
+ manager.add(new Action("Add...", factory.getImageDescriptor("add")) { //$NON-NLS-1$
@Override
public void run() {
super.run();
- doTreeRemove();
+ doTreeAdd();
}
});
}
-
- manager.add(new Separator());
- if (ui_node != null) {
- manager.add(new Action("Up", EditorsPlugin.getAndroidLogoDesc()) {
+ if (selected != null) {
+ if (selected != null) {
+ manager.add(new Action("Remove", factory.getImageDescriptor("delete")) { //$NON-NLS-1$
+ @Override
+ public void run() {
+ super.run();
+ doTreeRemove();
+ }
+ });
+ }
+ manager.add(new Separator());
+
+ manager.add(new Action("Up", factory.getImageDescriptor("up")) { //$NON-NLS-1$
@Override
public void run() {
super.run();
doTreeUp();
}
});
- }
-
- if (ui_node != null) {
- manager.add(new Action("Down", EditorsPlugin.getAndroidLogoDesc()) {
+ manager.add(new Action("Down", factory.getImageDescriptor("down")) { //$NON-NLS-1$
@Override
public void run() {
super.run();
@@ -555,6 +591,27 @@
}
/**
+ * Filters an ITreeSelection to only keep the {@link UiElementNode}s (in case there's
+ * something else in there).
+ *
+ * @return A new list of {@link UiElementNode} with at least one item or null.
+ */
+ @SuppressWarnings("unchecked")
+ private ArrayList<UiElementNode> filterSelection(ITreeSelection selection) {
+ ArrayList<UiElementNode> selected = new ArrayList<UiElementNode>();
+
+ for (Iterator it = selection.iterator(); it.hasNext(); ) {
+ Object selectedObj = it.next();
+
+ if (selectedObj instanceof UiElementNode) {
+ selected.add((UiElementNode) selectedObj);
+ }
+ }
+
+ return selected.size() > 0 ? selected : null;
+ }
+
+ /**
* Called when the "Add..." button next to the tree view is selected.
*
* Displays a selection dialog that lets the user select which kind of node
@@ -588,16 +645,11 @@
protected void doTreeRemove() {
ISelection selection = mTreeViewer.getSelection();
if (!selection.isEmpty() && selection instanceof ITreeSelection) {
- ITreeSelection tree_selection = (ITreeSelection) selection;
- Object first = tree_selection.getFirstElement();
- if (first instanceof UiElementNode) {
- final UiElementNode ui_node = (UiElementNode) first;
-
- mUiTreeActions.doRemove(ui_node, mTreeViewer.getControl().getShell());
- }
+ ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection);
+ mUiTreeActions.doRemove(selected, mTreeViewer.getControl().getShell());
}
}
-
+
/**
* Called when the "Up" button is selected.
* <p/>
@@ -607,13 +659,8 @@
protected void doTreeUp() {
ISelection selection = mTreeViewer.getSelection();
if (!selection.isEmpty() && selection instanceof ITreeSelection) {
- ITreeSelection tree_selection = (ITreeSelection) selection;
- Object first = tree_selection.getFirstElement();
- if (first instanceof UiElementNode) {
- final UiElementNode ui_node = (UiElementNode) first;
-
- mUiTreeActions.doUp(ui_node);
- }
+ ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection);
+ mUiTreeActions.doUp(selected);
}
}
@@ -626,13 +673,8 @@
protected void doTreeDown() {
ISelection selection = mTreeViewer.getSelection();
if (!selection.isEmpty() && selection instanceof ITreeSelection) {
- ITreeSelection tree_selection = (ITreeSelection) selection;
- Object first = tree_selection.getFirstElement();
- if (first instanceof UiElementNode) {
- final UiElementNode ui_node = (UiElementNode) first;
-
- mUiTreeActions.doDown(ui_node);
- }
+ ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection);
+ mUiTreeActions.doDown(selected);
}
}
@@ -653,7 +695,7 @@
@Override
protected void createToolBarActions(IManagedForm managedForm) {
- // pass
+ // Pass. Not used, toolbar actions are defined by createSectionActions().
}
@Override
@@ -686,14 +728,14 @@
}
/**
- * Adds a sort action to the tree viewer.
+ * An alphabetic sort action for the tree viewer.
*/
private class TreeSortAction extends Action {
private ViewerComparator mComparator;
public TreeSortAction() {
- setToolTipText("Sorts elements alphabetically.");
+ super("Sorts elements alphabetically.", AS_CHECK_BOX);
setImageDescriptor(IconFactory.getInstance().getImageDescriptor("az_sort")); //$NON-NLS-1$
if (mTreeViewer != null) {
@@ -703,7 +745,7 @@
}
/**
- * Called when the button is selected. Toggle the tree viewer comparator.
+ * Called when the button is selected. Toggles the tree viewer comparator.
*/
@Override
public void run() {
@@ -730,4 +772,97 @@
notifyResult(true /*success*/);
}
}
+
+ /**
+ * A filter on descriptor for the tree viewer.
+ * <p/>
+ * The tree viewer will contain many of these actions and only one can be enabled at a
+ * given time. When no action is selected, everything is displayed.
+ * <p/>
+ * Since "radio"-like actions do not allow for unselecting all of them, we manually
+ * handle the exclusive radio button-like property: when an action is selected, it manually
+ * removes all other actions as needed.
+ */
+ private class DescriptorFilterAction extends Action {
+
+ private final ElementDescriptor mDescriptor;
+ private ViewerFilter mFilter;
+
+ public DescriptorFilterAction(ElementDescriptor descriptor) {
+ super(String.format("Displays only %1$s elements.", descriptor.getUiName()),
+ AS_CHECK_BOX);
+
+ mDescriptor = descriptor;
+ setImageDescriptor(descriptor.getImageDescriptor());
+ }
+
+ /**
+ * Called when the button is selected.
+ * <p/>
+ * Find any existing {@link DescriptorFilter}s and remove them. Install ours.
+ */
+ @Override
+ public void run() {
+ super.run();
+
+ if (isChecked()) {
+ if (mFilter == null) {
+ // create filter when required
+ mFilter = new DescriptorFilter(this);
+ }
+
+ // we add our filter first, otherwise the UI might show the full list
+ mTreeViewer.addFilter(mFilter);
+
+ // Then remove the any other filters except ours. There should be at most
+ // one other filter, since that's how the actions are made to look like
+ // exclusive radio buttons.
+ for (ViewerFilter filter : mTreeViewer.getFilters()) {
+ if (filter instanceof DescriptorFilter && filter != mFilter) {
+ DescriptorFilterAction action = ((DescriptorFilter) filter).getAction();
+ action.setChecked(false);
+ mTreeViewer.removeFilter(filter);
+ }
+ }
+ } else if (mFilter != null){
+ mTreeViewer.removeFilter(mFilter);
+ }
+ }
+
+ /**
+ * Filters the tree viewer for the given descriptor.
+ * <p/>
+ * The filter is linked to the action so that an action can iterate through the list
+ * of filters and un-select the actions.
+ */
+ private class DescriptorFilter extends ViewerFilter {
+
+ private final DescriptorFilterAction mAction;
+
+ public DescriptorFilter(DescriptorFilterAction action) {
+ mAction = action;
+ }
+
+ public DescriptorFilterAction getAction() {
+ return mAction;
+ }
+
+ /**
+ * Returns true if an element should be displayed, that if the element or
+ * any of its parent matches the requested descriptor.
+ */
+ @Override
+ public boolean select(Viewer viewer, Object parentElement, Object element) {
+ while (element instanceof UiElementNode) {
+ UiElementNode uiNode = (UiElementNode)element;
+ if (uiNode.getDescriptor() == mDescriptor) {
+ return true;
+ }
+ element = uiNode.getUiParent();
+ }
+ return false;
+ }
+ }
+ }
+
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java
similarity index 91%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java
index 4c368d9..7fe44da 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java
@@ -26,7 +26,7 @@
/** Returns the current value of the node. */
public String getCurrentValue();
- /** Sets the current value of the node. */
+ /** Sets the current value of the node. Cannot be null (use an empty string). */
public void setCurrentValue(String value);
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiUpdateListener.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/IUiUpdateListener.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiUpdateListener.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/IUiUpdateListener.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAbstractTextAttributeNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiAbstractTextAttributeNode.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAbstractTextAttributeNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiAbstractTextAttributeNode.java
index 17b077a..5908574 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAbstractTextAttributeNode.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiAbstractTextAttributeNode.java
@@ -37,7 +37,7 @@
/** Prevent internal listener from firing when internally modifying the text */
private boolean mInternalTextModification;
- /** Last value read from the XML model */
+ /** Last value read from the XML model. Cannot be null. */
private String mCurrentValue = DEFAULT_VALUE;
public UiAbstractTextAttributeNode(AttributeDescriptor attributeDescriptor,
@@ -51,7 +51,7 @@
return mCurrentValue;
}
- /** Sets the current value of the node. */
+ /** Sets the current value of the node. Cannot be null (use an empty string). */
public final void setCurrentValue(String value) {
mCurrentValue = value;
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAttributeNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiAttributeNode.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAttributeNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiAttributeNode.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiDocumentNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiDocumentNode.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiDocumentNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiDocumentNode.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiElementNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiElementNode.java
similarity index 94%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiElementNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiElementNode.java
index 22b68b3..e0e9a40 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiElementNode.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiElementNode.java
@@ -16,9 +16,10 @@
package com.android.ide.eclipse.editors.uimodel;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor;
@@ -29,6 +30,7 @@
import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors;
import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener.UiUpdateState;
+import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.ui.IEditorInput;
@@ -206,6 +208,10 @@
AndroidManifestDescriptors.ANDROID_LABEL_ATTR);
}
if (attr == null || attr.length() == 0) {
+ attr = elem.getAttributeNS(AndroidConstants.NS_RESOURCES,
+ XmlDescriptors.PREF_KEY_ATTR);
+ }
+ if (attr == null || attr.length() == 0) {
attr = elem.getAttribute(ResourcesDescriptors.NAME_ATTR);
}
if (attr == null || attr.length() == 0) {
@@ -426,6 +432,13 @@
public AndroidEditor getEditor() {
return mUiParent == null ? mEditor : mUiParent.getEditor();
}
+
+ /**
+ * Returns the Android target data for the file being edited.
+ */
+ public AndroidTargetData getAndroidTarget() {
+ return getEditor().getTargetData();
+ }
/**
* @return A read-only version of the children collection.
@@ -447,7 +460,7 @@
}
return mReadOnlyUiAttributes;
}
-
+
/**
* @return A read-only version of the unknown attributes collection.
*/
@@ -564,7 +577,7 @@
return null;
}
-
+
/**
* Returns the {@link UiAttributeNode} matching this attribute descriptor or
* null if not found.
@@ -719,7 +732,16 @@
}
mXmlNode = doc.createElement(element_name);
- parentXmlNode.appendChild(mXmlNode);
+
+ Node xmlNextSibling = null;
+
+ UiElementNode uiNextSibling = getUiNextSibling();
+ if (uiNextSibling != null) {
+ xmlNextSibling = uiNextSibling.getXmlNode();
+ }
+
+ parentXmlNode.insertBefore(mXmlNode, xmlNextSibling);
+
// Insert a separator after the tag, to make it easier to read
Text sep = doc.createTextNode("\n");
parentXmlNode.appendChild(sep);
@@ -736,7 +758,7 @@
attr.setPrefix(desc.getXmlNsPrefix());
mXmlNode.getAttributes().setNamedItemNS(attr);
} else {
- UiAttributeNode ui_attr = mUiAttributes.get(attr_desc);
+ UiAttributeNode ui_attr = getInternalUiAttributes().get(attr_desc);
commitAttributeToXml(ui_attr, ui_attr.getCurrentValue());
}
}
@@ -873,7 +895,7 @@
false /* recursive */);
if (desc == null) {
// Unknown element. Simply ignore it.
- EditorsPlugin.log(IStatus.WARNING,
+ AdtPlugin.log(IStatus.WARNING,
"AndroidManifest: Ignoring unknown '%s' XML element", //$NON-NLS-1$
element_name);
} else {
@@ -953,7 +975,7 @@
* @param descriptor The {@link ElementDescriptor} that knows how to create the UI node.
* @return The new UI node.
*/
- private UiElementNode insertNewUiChild(int index, ElementDescriptor descriptor) {
+ public UiElementNode insertNewUiChild(int index, ElementDescriptor descriptor) {
UiElementNode ui_node;
ui_node = descriptor.createUiNode();
mUiChildren.add(index, ui_node);
@@ -1064,7 +1086,7 @@
listener.uiElementNodeUpdated(this, state);
} catch (Exception e) {
// prevent a crashing listener from crashing the whole invocation chain
- EditorsPlugin.log(e, "UIElement Listener failed: %s, state=%s", //$NON-NLS-1$
+ AdtPlugin.log(e, "UIElement Listener failed: %s, state=%s", //$NON-NLS-1$
getBreadcrumbTrailDescription(true),
state.toString());
}
@@ -1112,6 +1134,8 @@
* Note that the caller MUST ensure that modifying the underlying XML model is
* safe and must take care of marking the model as dirty if necessary.
*
+ * @see AndroidEditor#editXmlModel(Runnable)
+ *
* @param uiAttr The attribute node to commit. Must be a child of this UiElementNode.
* @param newValue The new value to set.
* @return True if the XML attribute was modified or removed, false if nothing changed.
@@ -1119,7 +1143,7 @@
public boolean commitAttributeToXml(UiAttributeNode uiAttr, String newValue) {
// Get (or create) the underlying XML element node that contains the attributes.
Node element = prepareCommit();
- if (element != null) {
+ if (element != null && uiAttr != null) {
String attrLocalName = uiAttr.getDescriptor().getXmlLocalName();
String attrNsUri = uiAttr.getDescriptor().getNamespaceUri();
@@ -1146,6 +1170,36 @@
}
/**
+ * Helper method to commit all dirty attributes values to XML.
+ * <p/>
+ * This method is useful if {@link #setAttributeValue(String, String, boolean)} has been
+ * called more than once and all the attributes marked as dirty must be commited to the
+ * XML. It calls {@link #commitAttributeToXml(UiAttributeNode, String)} on each dirty
+ * attribute.
+ * <p/>
+ * Note that the caller MUST ensure that modifying the underlying XML model is
+ * safe and must take care of marking the model as dirty if necessary.
+ *
+ * @see AndroidEditor#editXmlModel(Runnable)
+ *
+ * @return True if one or more values were actually modified or removed,
+ * false if nothing changed.
+ */
+ public boolean commitDirtyAttributesToXml() {
+ boolean result = false;
+ HashMap<AttributeDescriptor, UiAttributeNode> attributeMap = getInternalUiAttributes();
+
+ for (Entry<AttributeDescriptor, UiAttributeNode> entry : attributeMap.entrySet()) {
+ UiAttributeNode ui_attr = entry.getValue();
+ if (ui_attr.isDirty()) {
+ result |= commitAttributeToXml(ui_attr, ui_attr.getCurrentValue());
+ ui_attr.setDirty(false);
+ }
+ }
+ return result;
+ }
+
+ /**
* Returns the namespace prefix matching the requested namespace URI.
* If no such declaration is found, returns the default "android" prefix.
*
@@ -1226,13 +1280,21 @@
* This does not commit to the XML model. It does mark the attribute node as dirty.
* This is up to the caller.
*
+ * @see #commitAttributeToXml(UiAttributeNode, String)
+ * @see #commitDirtyAttributesToXml()
+ *
* @param attrXmlName The XML name of the attribute to modify
- * @param value The new value for the attribute.
+ * @param value The new value for the attribute. If set to null, the attribute is removed.
* @param override True if the value must be set even if one already exists.
+ * @return The {@link UiAttributeNode} that has been modified or null.
*/
- public void setAttributeValue(String attrXmlName, String value, boolean override) {
+ public UiAttributeNode setAttributeValue(String attrXmlName, String value, boolean override) {
HashMap<AttributeDescriptor, UiAttributeNode> attributeMap = getInternalUiAttributes();
+ if (value == null) {
+ value = ""; //$NON-NLS-1$ -- this removes an attribute
+ }
+
for (Entry<AttributeDescriptor, UiAttributeNode> entry : attributeMap.entrySet()) {
AttributeDescriptor ui_desc = entry.getKey();
if (ui_desc.getXmlLocalName().equals(attrXmlName)) {
@@ -1240,16 +1302,20 @@
// Not all attributes are editable, ignore those which are not
if (ui_attr instanceof IUiSettableAttributeNode) {
String current = ui_attr.getCurrentValue();
- if (override || current == null || current.length() == 0) {
+ // Only update (and mark as dirty) if the attribute did not have any
+ // value or if the value was different.
+ if (override || current == null || !current.equals(value)) {
((IUiSettableAttributeNode) ui_attr).setCurrentValue(value);
// mark the attribute as dirty since their internal content
// as been modified, but not the underlying XML model
ui_attr.setDirty(true);
+ return ui_attr;
}
}
break;
}
}
+ return null;
}
/**
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiFlagAttributeNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiFlagAttributeNode.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiFlagAttributeNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiFlagAttributeNode.java
index 4e0a8c7..ddcf0a0 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiFlagAttributeNode.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiFlagAttributeNode.java
@@ -16,7 +16,8 @@
package com.android.ide.eclipse.editors.uimodel;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.editors.AndroidEditor;
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.descriptors.FlagAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor;
@@ -138,8 +139,13 @@
}
if (values == null) {
- // or from the framework resource manager
- values = FrameworkResourceManager.getInstance().getValues(element_name, attr_name);
+ // or from the AndroidTargetData
+ UiElementNode uiNode = getUiParent();
+ AndroidEditor editor = uiNode.getEditor();
+ AndroidTargetData data = editor.getTargetData();
+ if (data != null) {
+ values = data.getAttributeValues(element_name, attr_name);
+ }
}
return values;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiListAttributeNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiListAttributeNode.java
similarity index 84%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiListAttributeNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiListAttributeNode.java
index 261e146..aaad0ce 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiListAttributeNode.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiListAttributeNode.java
@@ -16,9 +16,10 @@
package com.android.ide.eclipse.editors.uimodel;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.editors.AndroidEditor;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.descriptors.ListAttributeDescriptor;
@@ -110,7 +111,7 @@
String[] values = getPossibleValues();
if (values == null) {
- EditorsPlugin.log(IStatus.ERROR,
+ AdtPlugin.log(IStatus.ERROR,
"FrameworkResourceManager did not provide values yet for %1$s",
getDescriptor().getXmlLocalName());
} else {
@@ -150,21 +151,27 @@
}
if (values == null) {
- // or from the framework resource manager
- // get the great-grand-parent descriptor.
-
- // the parent should always exist.
- UiElementNode grandParentNode = uiParent.getUiParent();
-
- String greatGrandParentNodeName = null;
- if (grandParentNode != null) {
- UiElementNode greatGrandParentNode = grandParentNode.getUiParent();
- if (greatGrandParentNode != null) {
- greatGrandParentNodeName = greatGrandParentNode.getDescriptor().getXmlName();
+ // or from the AndroidTargetData
+ UiElementNode uiNode = getUiParent();
+ AndroidEditor editor = uiNode.getEditor();
+ AndroidTargetData data = editor.getTargetData();
+ if (data != null) {
+ // get the great-grand-parent descriptor.
+
+ // the parent should always exist.
+ UiElementNode grandParentNode = uiParent.getUiParent();
+
+ String greatGrandParentNodeName = null;
+ if (grandParentNode != null) {
+ UiElementNode greatGrandParentNode = grandParentNode.getUiParent();
+ if (greatGrandParentNode != null) {
+ greatGrandParentNodeName =
+ greatGrandParentNode.getDescriptor().getXmlName();
+ }
}
+
+ values = data.getAttributeValues(element_name, attr_name, greatGrandParentNodeName);
}
- values = FrameworkResourceManager.getInstance().getValues(element_name, attr_name,
- greatGrandParentNodeName);
}
return values;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java
similarity index 89%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java
index 132ccc0..1c1e1bd 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.uimodel;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.common.resources.IResourceRepository;
import com.android.ide.eclipse.common.resources.ResourceType;
import com.android.ide.eclipse.editors.AndroidEditor;
@@ -28,7 +28,6 @@
import com.android.ide.eclipse.editors.wizards.ReferenceChooserDialog;
import com.android.ide.eclipse.editors.wizards.ResourceChooser;
-import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
@@ -41,8 +40,6 @@
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.IEditorInput;
-import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.TableWrapData;
@@ -118,22 +115,19 @@
* containing the result.
*/
public String showDialog(Shell shell, String currentValue) {
- // we need to get the project of the manifest.
+ // we need to get the project of the file being edited.
UiElementNode uiNode = getUiParent();
AndroidEditor editor = uiNode.getEditor();
- IEditorInput input = editor.getEditorInput();
- if (input instanceof IFileEditorInput) {
- // from the file editor we can get the IFile object, and from it, the IProject.
- IFile file = ((IFileEditorInput)input).getFile();
- IProject project = file.getProject();
-
+ IProject project = editor.getProject();
+ if (project != null) {
// get the resource repository for this project and the system resources.
IResourceRepository projectRepository =
ResourceManager.getInstance().getProjectResources(project);
if (mType != null) {
- IResourceRepository systemRepository =
- FrameworkResourceManager.getInstance().getSystemResources();
+ // get the Target Data to get the system resources
+ AndroidTargetData data = editor.getTargetData();
+ IResourceRepository systemRepository = data.getSystemResources();
// open a resource chooser dialog for specified resource type.
ResourceChooser dlg = new ResourceChooser(mType,
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiSeparatorAttributeNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiSeparatorAttributeNode.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiSeparatorAttributeNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiSeparatorAttributeNode.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiTextAttributeNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiTextAttributeNode.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiTextAttributeNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiTextAttributeNode.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiTextValueNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiTextValueNode.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiTextValueNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiTextValueNode.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ConfigurationSelector.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ConfigurationSelector.java
similarity index 98%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ConfigurationSelector.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ConfigurationSelector.java
index 39cfc58..b7dffdd 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ConfigurationSelector.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ConfigurationSelector.java
@@ -604,6 +604,8 @@
onTextChange();
}
});
+
+ new Label(this, SWT.NONE).setText("(3 digit code)");
}
private void onTextChange() {
@@ -666,6 +668,8 @@
onTextChange();
}
});
+
+ new Label(this, SWT.NONE).setText("(1-3 digit code)");
}
private void onTextChange() {
@@ -731,6 +735,8 @@
onLanguageChange();
}
});
+
+ new Label(this, SWT.NONE).setText("(2 letter code)");
}
private void onLanguageChange() {
@@ -797,6 +803,8 @@
onRegionChange();
}
});
+
+ new Label(this, SWT.NONE).setText("(2 letter code)");
}
private void onRegionChange() {
@@ -1236,11 +1244,8 @@
String size1 = mSize1.getText();
String size2 = mSize2.getText();
- // if only one of the strings is empty, do nothing
- if ((size1.length() == 0) ^ (size2.length() == 0)) {
- return;
- } else if (size1.length() == 0 && size2.length() == 0) {
- // empty size, means no qualifier.
+ if (size1.length() == 0 || size2.length() == 0) {
+ // if one of the strings is empty, reset to no qualifier.
// Since the qualifier classes are immutable, and we don't want to
// remove the qualifier from the configuration, we create a new default one.
mSelectedConfiguration.setScreenDimensionQualifier(new ScreenDimensionQualifier());
@@ -1251,9 +1256,11 @@
if (qualifier != null) {
mSelectedConfiguration.setScreenDimensionQualifier(qualifier);
} else {
- // Failure! Looks like the value is wrong.
- // we do nothing in this case.
- return;
+ // Failure! Looks like the value is wrong, reset the qualifier
+ // Since the qualifier classes are immutable, and we don't want to
+ // remove the qualifier from the configuration, we create a new default one.
+ mSelectedConfiguration.setScreenDimensionQualifier(
+ new ScreenDimensionQualifier());
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java
similarity index 93%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java
index 2f3209b..b27dd4f 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java
@@ -17,18 +17,19 @@
package com.android.ide.eclipse.editors.wizards;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.ProjectChooserHelper;
import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors;
import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration;
import com.android.ide.eclipse.editors.resources.configurations.ResourceQualifier;
import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors;
import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType;
import com.android.ide.eclipse.editors.wizards.ConfigurationSelector.ConfigurationState;
-import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
@@ -184,7 +185,7 @@
"Layout", // UI name
"An XML file that describes a screen layout.", // tooltip
ResourceFolderType.LAYOUT, // folder type
- LayoutDescriptors.getInstance().getDescriptor(), // root seed
+ AndroidTargetData.DESCRIPTOR_LAYOUT, // root seed
"LinearLayout", // default root
AndroidConstants.NS_RESOURCES, // xmlns
"android:layout_width=\"wrap_content\"\n" + // default attributes
@@ -209,7 +210,7 @@
new TypeInfo("Preference", // UI name
"An XML file that describes preferences.", // tooltip
ResourceFolderType.XML, // folder type
- XmlDescriptors.getInstance().getPreferencesDescriptor(), // root seed
+ AndroidTargetData.DESCRIPTOR_PREFERENCES, // root seed
AndroidConstants.CLASS_PREFERENCE_SCREEN, // default root
AndroidConstants.NS_RESOURCES, // xmlns
null // default attributes
@@ -217,7 +218,7 @@
new TypeInfo("Searchable", // UI name
"An XML file that describes a searchable [TODO].", // tooltip
ResourceFolderType.XML, // folder type
- XmlDescriptors.getInstance().getSearchableDescriptor(), // root seed
+ AndroidTargetData.DESCRIPTOR_SEARCHABLE, // root seed
null, // default root
AndroidConstants.NS_RESOURCES, // xmlns
null // default attributes
@@ -431,6 +432,11 @@
mProjectTextField = new Text(parent, SWT.BORDER);
mProjectTextField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
mProjectTextField.setToolTipText(tooltip);
+ mProjectTextField.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ onProjectFieldUpdated();
+ }
+ });
mProjectBrowseButton = new Button(parent, SWT.NONE);
mProjectBrowseButton.setText("Browse...");
@@ -655,9 +661,10 @@
*/
private void initializeRootValues() {
for (TypeInfo type : sTypes) {
+ // Clear all the roots for this type
ArrayList<String> roots = type.getRoots();
if (roots.size() > 0) {
- continue;
+ roots.clear();
}
// depending of the type of the seed, initialize the root in different ways
@@ -671,13 +678,22 @@
for (String value : (String[]) rootSeed) {
roots.add(value);
}
- } else if (rootSeed instanceof ElementDescriptor) {
- // The seed is an element descriptor or a document descriptor.
+ } else if (rootSeed instanceof Integer && mProject != null) {
+ // The seed is a descriptor reference defined in AndroidTargetData.DESCRIPTOR_*
// In this case add all the children element descriptors defined, recursively,
// and avoid infinite recursion by keeping track of what has already been added.
+
+ // Note: if project is null, the root list will be empty since it has been
+ // cleared above.
+
+ // get the AndroidTargetData from the project
+ IAndroidTarget target = Sdk.getCurrent().getTarget(mProject);
+ AndroidTargetData data = Sdk.getCurrent().getTargetData(target);
+ ElementDescriptor descriptor = data.getDescriptorProvider(
+ (Integer)rootSeed).getDescriptor();
HashSet<ElementDescriptor> visited = new HashSet<ElementDescriptor>();
- initRootElementDescriptor(roots, (ElementDescriptor) rootSeed, visited);
+ initRootElementDescriptor(roots, descriptor, visited);
// Sort alphabetically.
Collections.sort(roots);
@@ -708,6 +724,35 @@
}
}
}
+
+ /**
+ * Callback called when the user edits the project text field.
+ */
+ private void onProjectFieldUpdated() {
+ String project = mProjectTextField.getText();
+
+ // Is this a valid project?
+ IJavaProject[] projects = mProjectChooserHelper.getAndroidProjects(null /*javaModel*/);
+ IProject found = null;
+ for (IJavaProject p : projects) {
+ if (p.getProject().getName().equals(project)) {
+ found = p.getProject();
+ break;
+ }
+ }
+
+ if (found != mProject) {
+ mProject = found;
+
+ // update the Type with the new descriptors.
+ initializeRootValues();
+
+ // update the combo
+ updateRootCombo(getSelectedType());
+
+ validatePage();
+ }
+ }
/**
* Callback called when the user uses the "Browse Projects" button.
@@ -717,6 +762,13 @@
if (p != null) {
mProject = p.getProject();
mProjectTextField.setText(mProject.getName());
+
+ // update the Type with the new descriptors.
+ initializeRootValues();
+
+ // update the combo
+ updateRootCombo(getSelectedType());
+
validatePage();
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java
similarity index 93%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java
index 8318e4b..125102b 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java
@@ -18,7 +18,7 @@
package com.android.ide.eclipse.editors.wizards;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.IconFactory;
import com.android.ide.eclipse.editors.wizards.NewXmlFileCreationPage.TypeInfo;
@@ -116,7 +116,7 @@
try {
IDE.openEditor(page, file);
} catch (PartInitException e) {
- EditorsPlugin.log(e, "Failed to create %1$s: missing type", //$NON-NLS-1$
+ AdtPlugin.log(e, "Failed to create %1$s: missing type", //$NON-NLS-1$
file.getFullPath().toString());
}
}
@@ -133,7 +133,7 @@
boolean need_delete = false;
if (file.exists()) {
- if (!EditorsPlugin.displayPrompt("New Android XML File",
+ if (!AdtPlugin.displayPrompt("New Android XML File",
String.format("Do you want to overwrite the file %1$s ?", name))) {
// abort if user selects cancel.
return null;
@@ -146,14 +146,14 @@
TypeInfo type = mMainPage.getSelectedType();
if (type == null) {
// this is not expected to happen
- EditorsPlugin.log(IStatus.ERROR, "Failed to create %1$s: missing type", name); //$NON-NLS-1$
+ AdtPlugin.log(IStatus.ERROR, "Failed to create %1$s: missing type", name); //$NON-NLS-1$
return null;
}
String xmlns = type.getXmlns();
String root = mMainPage.getRootElement();
if (root == null) {
// this is not expected to happen
- EditorsPlugin.log(IStatus.ERROR, "Failed to create %1$s: missing root element", //$NON-NLS-1$
+ AdtPlugin.log(IStatus.ERROR, "Failed to create %1$s: missing root element", //$NON-NLS-1$
file.toString());
return null;
}
@@ -191,7 +191,7 @@
}
error = String.format("Failed to generate %1$s: %2$s", name, error);
- EditorsPlugin.displayError("New Android XML File", error);
+ AdtPlugin.displayError("New Android XML File", error);
return null;
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ReferenceChooserDialog.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ReferenceChooserDialog.java
similarity index 97%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ReferenceChooserDialog.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ReferenceChooserDialog.java
index 446cc14..d3ff334 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ReferenceChooserDialog.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ReferenceChooserDialog.java
@@ -16,6 +16,7 @@
package com.android.ide.eclipse.editors.wizards;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.resources.IResourceRepository;
import com.android.ide.eclipse.common.resources.ResourceItem;
@@ -187,16 +188,16 @@
IStatus status;
if (treeSelection != null) {
if (treeSelection.getSegmentCount() == 2) {
- status = new Status(IStatus.OK, AndroidConstants.EDITORS_PLUGIN_ID,
+ status = new Status(IStatus.OK, AdtPlugin.PLUGIN_ID,
IStatus.OK, "", //$NON-NLS-1$
null);
} else {
- status = new Status(IStatus.ERROR, AndroidConstants.EDITORS_PLUGIN_ID,
+ status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
IStatus.ERROR, "You must select a Resource Item",
null);
}
} else {
- status = new Status(IStatus.ERROR, AndroidConstants.EDITORS_PLUGIN_ID,
+ status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
IStatus.ERROR, "", //$NON-NLS-1$
null);
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceChooser.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ResourceChooser.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceChooser.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ResourceChooser.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceContentProvider.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ResourceContentProvider.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceContentProvider.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ResourceContentProvider.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceLabelProvider.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ResourceLabelProvider.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceLabelProvider.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ResourceLabelProvider.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlContentAssist.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlContentAssist.java
similarity index 86%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlContentAssist.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlContentAssist.java
index bb010e3..f28b523 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlContentAssist.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlContentAssist.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.xml;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.editors.AndroidContentAssist;
-import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
/**
* Content Assist Processor for /res/xml XML files
@@ -28,6 +28,6 @@
* Constructor for LayoutContentAssist
*/
public XmlContentAssist() {
- super(XmlDescriptors.getInstance().getDescriptor().getChildren());
+ super(AndroidTargetData.DESCRIPTOR_XML);
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlEditor.java
similarity index 61%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlEditor.java
index 40d655a..b1900ae 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlEditor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlEditor.java
@@ -16,16 +16,19 @@
package com.android.ide.eclipse.editors.xml;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.FirstElementParser;
import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
-import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PartInitException;
@@ -37,19 +40,16 @@
*/
public class XmlEditor extends AndroidEditor {
- public static final String ID = "com.android.ide.eclipse.editors.xml.XmlEditor"; //$NON-NLS-1$
+ public static final String ID = AndroidConstants.EDITORS_NAMESPACE + ".xml.XmlEditor"; //$NON-NLS-1$
/** Root node of the UI element hierarchy */
private UiDocumentNode mUiRootNode;
- /** Listener to update the root node if the resource framework changes */
- private Runnable mResourceRefreshListener;
/**
* Creates the form editor for resources XML files.
*/
public XmlEditor() {
super();
- initUiRootNode();
}
/**
@@ -72,19 +72,25 @@
* @return True if the {@link XmlEditor} can handle that file.
*/
public static boolean canHandleFile(IFile file) {
-
- FirstElementParser.Result result = FirstElementParser.parse(
- file.getLocation().toOSString(),
- AndroidConstants.NS_RESOURCES);
+ // we need the target of the file's project to access the descriptors.
+ IProject project = file.getProject();
+ IAndroidTarget target = Sdk.getCurrent().getTarget(project);
+ if (target != null) {
+ AndroidTargetData data = Sdk.getCurrent().getTargetData(target);
- if (result != null) {
- String name = result.getElement();
- if (name != null && result.getXmlnsPrefix() != null) {
- DocumentDescriptor desc = XmlDescriptors.getInstance().getDescriptor();
- for (ElementDescriptor elem : desc.getChildren()) {
- if (elem.getXmlName().equals(name)) {
- // This is an element that this document can handle
- return true;
+ FirstElementParser.Result result = FirstElementParser.parse(
+ file.getLocation().toOSString(),
+ AndroidConstants.NS_RESOURCES);
+
+ if (result != null) {
+ String name = result.getElement();
+ if (name != null && result.getXmlnsPrefix() != null) {
+ DocumentDescriptor desc = data.getXmlDescriptors().getDescriptor();
+ for (ElementDescriptor elem : desc.getChildren()) {
+ if (elem.getXmlName().equals(name)) {
+ // This is an element that this document can handle
+ return true;
+ }
}
}
}
@@ -95,15 +101,6 @@
// ---- Base Class Overrides ----
- @Override
- public void dispose() {
- if (mResourceRefreshListener != null) {
- EditorsPlugin.getDefault().removeResourceChangedListener(mResourceRefreshListener);
- mResourceRefreshListener = null;
- }
- super.dispose();
- }
-
/**
* Returns whether the "save as" operation is supported by this editor.
* <p/>
@@ -125,10 +122,10 @@
try {
addPage(new XmlTreePage(this));
} catch (PartInitException e) {
- EditorsPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
+ AdtPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
}
- }
+ }
/* (non-java doc)
* Change the tab/title name to include the project name.
@@ -150,35 +147,55 @@
*/
@Override
protected void xmlModelChanged(Document xml_doc) {
+ // init the ui root on demand
+ initUiRootNode(false /*force*/);
+
mUiRootNode.loadFromXmlNode(xml_doc);
super.xmlModelChanged(xml_doc);
}
-
- // ---- Local Methods ----
-
/**
* Creates the initial UI Root Node, including the known mandatory elements.
+ * @param force if true, a new UiRootNode is recreated even if it already exists.
*/
- private void initUiRootNode() {
+ @Override
+ protected void initUiRootNode(boolean force) {
// The root UI node is always created, even if there's no corresponding XML node.
- if (mUiRootNode == null) {
- DocumentDescriptor desc = XmlDescriptors.getInstance().getDescriptor();
+ if (mUiRootNode == null || force) {
+ Document doc = null;
+ if (mUiRootNode != null) {
+ doc = mUiRootNode.getXmlDocument();
+ }
+
+ // get the target data from the opened file (and its project)
+ AndroidTargetData data = getTargetData();
+
+ DocumentDescriptor desc;
+ if (data == null) {
+ desc = new DocumentDescriptor("temp", null /*children*/);
+ } else {
+ desc = data.getXmlDescriptors().getDescriptor();
+ }
+
mUiRootNode = (UiDocumentNode) desc.createUiNode();
mUiRootNode.setEditor(this);
- // Add a listener to refresh the root node if the resource framework changes
- // by forcing it to parse its own XML
- mResourceRefreshListener = new Runnable() {
- public void run() {
- commitPages(false /* onSave */);
-
- mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlNode());
- }
- };
- EditorsPlugin.getDefault().addResourceChangedListener(mResourceRefreshListener);
- mResourceRefreshListener.run();
+ onDescriptorsChanged(doc);
}
}
+
+ // ---- Local Methods ----
+
+ /**
+ * Reloads the UI manifest node from the XML, and calls the pages to update.
+ */
+ private void onDescriptorsChanged(Document document) {
+ if (document != null) {
+ mUiRootNode.loadFromXmlNode(document);
+ } else {
+ mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlNode());
+ }
+ }
+
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlSourceViewerConfig.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlSourceViewerConfig.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlSourceViewerConfig.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlSourceViewerConfig.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlTreePage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlTreePage.java
similarity index 94%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlTreePage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlTreePage.java
index 5bb0f72..91ce6dd 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlTreePage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlTreePage.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.xml;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.ui.tree.UiTreeBlock;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
@@ -49,7 +49,7 @@
super.createFormContent(managedForm);
ScrolledForm form = managedForm.getForm();
form.setText("Android Xml");
- form.setImage(EditorsPlugin.getAndroidLogo());
+ form.setImage(AdtPlugin.getAndroidLogo());
UiElementNode rootNode = mEditor.getUiRootNode();
UiTreeBlock block = new UiTreeBlock(mEditor, rootNode,
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java
similarity index 90%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java
index 14cb9d6..31b4c61 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java
@@ -24,6 +24,7 @@
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor;
import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor;
@@ -36,10 +37,11 @@
* Description of the /res/xml structure.
* Currently supports the <searchable> and <preferences> root nodes.
*/
-public class XmlDescriptors {
+public final class XmlDescriptors implements IDescriptorProvider {
- /** Singleton instance */
- private static XmlDescriptors sThis;
+ // Public attributes names, attributes descriptors and elements descriptors referenced
+ // elsewhere.
+ public static final String PREF_KEY_ATTR = "key"; //$NON-NLS-1$
/** The root document descriptor for both searchable and preferences. */
private DocumentDescriptor mDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$
@@ -50,19 +52,15 @@
/** The root document descriptor for preferences. */
private DocumentDescriptor mPrefDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$
- /** Returns a singleton instance of the {@link XmlDescriptors}. */
- public static synchronized XmlDescriptors getInstance() {
- if (sThis == null) {
- sThis = new XmlDescriptors();
- }
- return sThis;
- }
-
/** @return the root descriptor for both searchable and preferences. */
public DocumentDescriptor getDescriptor() {
return mDescriptor;
}
+ public ElementDescriptor[] getRootElementDescriptors() {
+ return mDescriptor.getChildren();
+ }
+
/** @return the root descriptor for searchable. */
public DocumentDescriptor getSearchableDescriptor() {
return mSearchDescriptor;
@@ -72,6 +70,30 @@
public DocumentDescriptor getPreferencesDescriptor() {
return mPrefDescriptor;
}
+
+ public IDescriptorProvider getSearchableProvider() {
+ return new IDescriptorProvider() {
+ public ElementDescriptor getDescriptor() {
+ return mSearchDescriptor;
+ }
+
+ public ElementDescriptor[] getRootElementDescriptors() {
+ return mSearchDescriptor.getChildren();
+ }
+ };
+ }
+
+ public IDescriptorProvider getPreferencesProvider() {
+ return new IDescriptorProvider() {
+ public ElementDescriptor getDescriptor() {
+ return mPrefDescriptor;
+ }
+
+ public ElementDescriptor[] getRootElementDescriptors() {
+ return mPrefDescriptor.getChildren();
+ }
+ };
+ }
/**
* Updates the document descriptor.
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/.classpath b/tools/eclipse/plugins/com.android.ide.eclipse.common/.classpath
deleted file mode 100644
index a7b3dc1..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/.classpath
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
- <classpathentry kind="lib" path="androidprefs.jar"/>
- <classpathentry kind="lib" path="sdkstats.jar"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/.project b/tools/eclipse/plugins/com.android.ide.eclipse.common/.project
deleted file mode 100644
index 510efb7..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/.project
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>common</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.ManifestBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.SchemaBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.pde.PluginNature</nature>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
-</projectDescription>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/META-INF/MANIFEST.MF b/tools/eclipse/plugins/com.android.ide.eclipse.common/META-INF/MANIFEST.MF
deleted file mode 100644
index dad85a6..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,22 +0,0 @@
-Manifest-Version: 1.0
-Bundle-ManifestVersion: 2
-Bundle-Name: Android Common Plugin
-Bundle-SymbolicName: com.android.ide.eclipse.common;singleton:=true
-Bundle-Version: 0.8.1.qualifier
-Bundle-ClassPath: .,
- sdkstats.jar,
- androidprefs.jar
-Bundle-Vendor: The Android Open Source Project
-Eclipse-LazyStart: true
-Export-Package: com.android.ide.eclipse.common,
- com.android.ide.eclipse.common.project,
- com.android.ide.eclipse.common.resources
-Require-Bundle: org.eclipse.core.resources,
- org.eclipse.core.runtime,
- org.eclipse.jdt.core,
- org.eclipse.ui.console,
- org.eclipse.ui,
- org.eclipse.jdt.ui,
- org.eclipse.jface.text,
- org.eclipse.ui.editors
-Bundle-Activator: com.android.ide.eclipse.common.CommonPlugin
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/NOTICE b/tools/eclipse/plugins/com.android.ide.eclipse.common/NOTICE
deleted file mode 100644
index 49c101d..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/NOTICE
+++ /dev/null
@@ -1,224 +0,0 @@
-*Eclipse Public License - v 1.0*
-
-THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
-PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF
-THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
-
-*1. DEFINITIONS*
-
-"Contribution" means:
-
-a) in the case of the initial Contributor, the initial code and
-documentation distributed under this Agreement, and
-b) in the case of each subsequent Contributor:
-
-i) changes to the Program, and
-
-ii) additions to the Program;
-
-where such changes and/or additions to the Program originate from and
-are distributed by that particular Contributor. A Contribution
-'originates' from a Contributor if it was added to the Program by such
-Contributor itself or anyone acting on such Contributor's behalf.
-Contributions do not include additions to the Program which: (i) are
-separate modules of software distributed in conjunction with the Program
-under their own license agreement, and (ii) are not derivative works of
-the Program.
-
-"Contributor" means any person or entity that distributes the Program.
-
-"Licensed Patents " mean patent claims licensable by a Contributor which
-are necessarily infringed by the use or sale of its Contribution alone
-or when combined with the Program.
-
-"Program" means the Contributions distributed in accordance with this
-Agreement.
-
-"Recipient" means anyone who receives the Program under this Agreement,
-including all Contributors.
-
-*2. GRANT OF RIGHTS*
-
-a) Subject to the terms of this Agreement, each Contributor hereby
-grants Recipient a non-exclusive, worldwide, royalty-free copyright
-license to reproduce, prepare derivative works of, publicly display,
-publicly perform, distribute and sublicense the Contribution of such
-Contributor, if any, and such derivative works, in source code and
-object code form.
-
-b) Subject to the terms of this Agreement, each Contributor hereby
-grants Recipient a non-exclusive, worldwide, royalty-free patent license
-under Licensed Patents to make, use, sell, offer to sell, import and
-otherwise transfer the Contribution of such Contributor, if any, in
-source code and object code form. This patent license shall apply to the
-combination of the Contribution and the Program if, at the time the
-Contribution is added by the Contributor, such addition of the
-Contribution causes such combination to be covered by the Licensed
-Patents. The patent license shall not apply to any other combinations
-which include the Contribution. No hardware per se is licensed hereunder.
-
-c) Recipient understands that although each Contributor grants the
-licenses to its Contributions set forth herein, no assurances are
-provided by any Contributor that the Program does not infringe the
-patent or other intellectual property rights of any other entity. Each
-Contributor disclaims any liability to Recipient for claims brought by
-any other entity based on infringement of intellectual property rights
-or otherwise. As a condition to exercising the rights and licenses
-granted hereunder, each Recipient hereby assumes sole responsibility to
-secure any other intellectual property rights needed, if any. For
-example, if a third party patent license is required to allow Recipient
-to distribute the Program, it is Recipient's responsibility to acquire
-that license before distributing the Program.
-
-d) Each Contributor represents that to its knowledge it has sufficient
-copyright rights in its Contribution, if any, to grant the copyright
-license set forth in this Agreement.
-
-*3. REQUIREMENTS*
-
-A Contributor may choose to distribute the Program in object code form
-under its own license agreement, provided that:
-
-a) it complies with the terms and conditions of this Agreement; and
-
-b) its license agreement:
-
-i) effectively disclaims on behalf of all Contributors all warranties
-and conditions, express and implied, including warranties or conditions
-of title and non-infringement, and implied warranties or conditions of
-merchantability and fitness for a particular purpose;
-
-ii) effectively excludes on behalf of all Contributors all liability for
-damages, including direct, indirect, special, incidental and
-consequential damages, such as lost profits;
-
-iii) states that any provisions which differ from this Agreement are
-offered by that Contributor alone and not by any other party; and
-
-iv) states that source code for the Program is available from such
-Contributor, and informs licensees how to obtain it in a reasonable
-manner on or through a medium customarily used for software exchange.
-
-When the Program is made available in source code form:
-
-a) it must be made available under this Agreement; and
-
-b) a copy of this Agreement must be included with each copy of the Program.
-
-Contributors may not remove or alter any copyright notices contained
-within the Program.
-
-Each Contributor must identify itself as the originator of its
-Contribution, if any, in a manner that reasonably allows subsequent
-Recipients to identify the originator of the Contribution.
-
-*4. COMMERCIAL DISTRIBUTION*
-
-Commercial distributors of software may accept certain responsibilities
-with respect to end users, business partners and the like. While this
-license is intended to facilitate the commercial use of the Program, the
-Contributor who includes the Program in a commercial product offering
-should do so in a manner which does not create potential liability for
-other Contributors. Therefore, if a Contributor includes the Program in
-a commercial product offering, such Contributor ("Commercial
-Contributor") hereby agrees to defend and indemnify every other
-Contributor ("Indemnified Contributor") against any losses, damages and
-costs (collectively "Losses") arising from claims, lawsuits and other
-legal actions brought by a third party against the Indemnified
-Contributor to the extent caused by the acts or omissions of such
-Commercial Contributor in connection with its distribution of the
-Program in a commercial product offering. The obligations in this
-section do not apply to any claims or Losses relating to any actual or
-alleged intellectual property infringement. In order to qualify, an
-Indemnified Contributor must: a) promptly notify the Commercial
-Contributor in writing of such claim, and b) allow the Commercial
-Contributor to control, and cooperate with the Commercial Contributor
-in, the defense and any related settlement negotiations. The Indemnified
-Contributor may participate in any such claim at its own expense.
-
-For example, a Contributor might include the Program in a commercial
-product offering, Product X. That Contributor is then a Commercial
-Contributor. If that Commercial Contributor then makes performance
-claims, or offers warranties related to Product X, those performance
-claims and warranties are such Commercial Contributor's responsibility
-alone. Under this section, the Commercial Contributor would have to
-defend claims against the other Contributors related to those
-performance claims and warranties, and if a court requires any other
-Contributor to pay any damages as a result, the Commercial Contributor
-must pay those damages.
-
-*5. NO WARRANTY*
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED
-ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
-EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES
-OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR
-A PARTICULAR PURPOSE. Each Recipient is solely responsible for
-determining the appropriateness of using and distributing the Program
-and assumes all risks associated with its exercise of rights under this
-Agreement , including but not limited to the risks and costs of program
-errors, compliance with applicable laws, damage to or loss of data,
-programs or equipment, and unavailability or interruption of operations.
-
-*6. DISCLAIMER OF LIABILITY*
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
-ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
-WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
-DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
-HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-*7. GENERAL*
-
-If any provision of this Agreement is invalid or unenforceable under
-applicable law, it shall not affect the validity or enforceability of
-the remainder of the terms of this Agreement, and without further action
-by the parties hereto, such provision shall be reformed to the minimum
-extent necessary to make such provision valid and enforceable.
-
-If Recipient institutes patent litigation against any entity (including
-a cross-claim or counterclaim in a lawsuit) alleging that the Program
-itself (excluding combinations of the Program with other software or
-hardware) infringes such Recipient's patent(s), then such Recipient's
-rights granted under Section 2(b) shall terminate as of the date such
-litigation is filed.
-
-All Recipient's rights under this Agreement shall terminate if it fails
-to comply with any of the material terms or conditions of this Agreement
-and does not cure such failure in a reasonable period of time after
-becoming aware of such noncompliance. If all Recipient's rights under
-this Agreement terminate, Recipient agrees to cease use and distribution
-of the Program as soon as reasonably practicable. However, Recipient's
-obligations under this Agreement and any licenses granted by Recipient
-relating to the Program shall continue and survive.
-
-Everyone is permitted to copy and distribute copies of this Agreement,
-but in order to avoid inconsistency the Agreement is copyrighted and may
-only be modified in the following manner. The Agreement Steward reserves
-the right to publish new versions (including revisions) of this
-Agreement from time to time. No one other than the Agreement Steward has
-the right to modify this Agreement. The Eclipse Foundation is the
-initial Agreement Steward. The Eclipse Foundation may assign the
-responsibility to serve as the Agreement Steward to a suitable separate
-entity. Each new version of the Agreement will be given a distinguishing
-version number. The Program (including Contributions) may always be
-distributed subject to the version of the Agreement under which it was
-received. In addition, after a new version of the Agreement is
-published, Contributor may elect to distribute the Program (including
-its Contributions) under the new version. Except as expressly stated in
-Sections 2(a) and 2(b) above, Recipient receives no rights or licenses
-to the intellectual property of any Contributor under this Agreement,
-whether expressly, by implication, estoppel or otherwise. All rights in
-the Program not expressly granted under this Agreement are reserved.
-
-This Agreement is governed by the laws of the State of New York and the
-intellectual property laws of the United States of America. No party to
-this Agreement will bring a legal action under this Agreement more than
-one year after the cause of action arose. Each party waives its rights
-to a jury trial in any resulting litigation.
-
-
-
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/build.properties b/tools/eclipse/plugins/com.android.ide.eclipse.common/build.properties
deleted file mode 100644
index 4c9981d..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/build.properties
+++ /dev/null
@@ -1,7 +0,0 @@
-source.. = src/
-output.. = bin/
-bin.includes = META-INF/,\
- .,\
- sdkstats.jar,\
- plugin.xml,\
- androidprefs.jar
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/plugin.xml b/tools/eclipse/plugins/com.android.ide.eclipse.common/plugin.xml
deleted file mode 100644
index 115eb97..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/plugin.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?eclipse version="3.2"?>
-<plugin>
- <extension
- id="com.android.ide.eclipse.common.xmlProblem"
- name="XML Problem"
- point="org.eclipse.core.resources.markers">
- <super type="org.eclipse.core.resources.problemmarker"/>
- <super type="org.eclipse.core.resources.textmarker"/>
- <persistent value="true"/>
- </extension>
- <extension
- id="com.android.ide.eclipse.common.aaptProblem"
- name="aapt Problem"
- point="org.eclipse.core.resources.markers">
- <super type="org.eclipse.core.resources.problemmarker"/>
- <super type="org.eclipse.core.resources.textmarker"/>
- <persistent value="true"/>
- </extension>
- <extension
- id="com.android.ide.eclipse.common.aidlProblem"
- name="aidl Problem"
- point="org.eclipse.core.resources.markers">
- <super type="org.eclipse.core.resources.problemmarker"/>
- <super type="org.eclipse.core.resources.textmarker"/>
- <persistent value="true"/>
- </extension>
- <extension
- id="com.android.ide.eclipse.common.androidProblem"
- name="Android Problem"
- point="org.eclipse.core.resources.markers">
- <super type="org.eclipse.core.resources.problemmarker"/>
- <super type="org.eclipse.core.resources.textmarker"/>
- <persistent value="true"/>
- </extension>
- <extension
- point="org.eclipse.ui.preferencePages">
- <page
- category="com.android.ide.eclipse.preferences.main"
- class="com.android.ide.eclipse.common.preferences.UsagePreferencePage"
- id="com.android.ide.eclipse.common.preferences.UsagePreferencePage"
- name="Usage Stats"/>
- </extension>
-</plugin>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/CommonPlugin.java b/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/CommonPlugin.java
deleted file mode 100644
index cfee50f..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/CommonPlugin.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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.ide.eclipse.common;
-
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.IWorkbench;
-import org.eclipse.ui.console.ConsolePlugin;
-import org.eclipse.ui.console.IConsole;
-import org.eclipse.ui.console.MessageConsole;
-import org.eclipse.ui.plugin.AbstractUIPlugin;
-import org.osgi.framework.BundleContext;
-
-
-/**
- * The activator class controls the plug-in life cycle
- */
-public class CommonPlugin extends AbstractUIPlugin {
-
- // The plug-in ID
- public static final String PLUGIN_ID = "com.android.ide.eclipse.common"; // $NON-NLS-1$
-
- // The shared instance
- private static CommonPlugin sPlugin;
-
- // The global android console
- private MessageConsole mAndroidConsole;
-
- /**
- * The constructor
- */
- public CommonPlugin() {
- // pass
- }
-
- /**
- * Returns the shared instance
- *
- * @return the shared instance
- */
- public static CommonPlugin getDefault() {
- return sPlugin;
- }
-
- /** Returns the global android console */
- public MessageConsole getAndroidConsole() {
- return mAndroidConsole;
- }
-
- /**
- * The <code>AbstractUIPlugin</code> implementation of this <code>Plugin</code>
- * method refreshes the plug-in actions. Subclasses may extend this method,
- * but must send super <b>first</b>.
- *
- * {@inheritDoc}
- */
- @Override
- public void start(BundleContext context) throws Exception {
- super.start(context);
- sPlugin = this;
-
- /*
- * WARNING: think before adding any initialization here as plugins are dynamically
- * started and since no UI is being displayed by this plugin, it'll only start when
- * another plugin accesses some of its code.
- */
-
- // set the default android console.
- mAndroidConsole = new MessageConsole("Android", null); //$NON-NLS-1$
- ConsolePlugin.getDefault().getConsoleManager().addConsoles(
- new IConsole[] { mAndroidConsole });
- }
-
- /**
- * The <code>AbstractUIPlugin</code> implementation of this <code>Plugin</code>
- * method saves this plug-in's preference and dialog stores and shuts down
- * its image registry (if they are in use). Subclasses may extend this
- * method, but must send super <b>last</b>. A try-finally statement should
- * be used where necessary to ensure that <code>super.shutdown()</code> is
- * always done.
- *
- * {@inheritDoc}
- */
- @Override
- public void stop(BundleContext context) throws Exception {
- sPlugin = null;
- super.stop(context);
- }
-
- /**
- * Logs a message to the default Eclipse log.
- *
- * @param severity One of IStatus' severity codes: OK, ERROR, INFO, WARNING or CANCEL.
- * @param format The format string, like for String.format().
- * @param args The arguments for the format string, like for String.format().
- */
- public static void log(int severity, String format, Object ... args) {
- String message = String.format(format, args);
- Status status = new Status(severity, PLUGIN_ID, message);
- getDefault().getLog().log(status);
- }
-
- /**
- * Logs an exception to the default Eclipse log.
- * <p/>
- * The status severity is always set to ERROR.
- *
- * @param exception The exception to log. Its call trace will be recorded.
- * @param format The format string, like for String.format().
- * @param args The arguments for the format string, like for String.format().
- */
- public static void log(Throwable exception, String format, Object ... args) {
- String message = String.format(format, args);
- Status status = new Status(IStatus.ERROR, PLUGIN_ID, message, exception);
- getDefault().getLog().log(status);
- }
-
- private static Display getDisplay() {
- IWorkbench bench = sPlugin.getWorkbench();
- if (bench!=null) {
- return bench.getDisplay();
- }
- return null;
- }
-
- /**
- * Display a yes/no question dialog box. This dialog is opened synchronously in the ui thread,
- * therefore this message can be called from any thread.
- * @param title The title of the dialog box
- * @param message The error message
- * @return true if OK was clicked.
- */
- public final static boolean displayPrompt(final String title, final String message) {
- // get the current Display and Shell
- final Display display = getDisplay();
-
- // we need to ask the user what he wants to do.
- final Boolean[] wrapper = new Boolean[] { new Boolean(false) };
- display.syncExec(new Runnable() {
- public void run() {
- Shell shell = display.getActiveShell();
- wrapper[0] = new Boolean(MessageDialog.openQuestion(shell, title, message));
- }
- });
- return wrapper[0].booleanValue();
- }
-
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/FrameworkResourceManager.java b/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/FrameworkResourceManager.java
deleted file mode 100644
index 3f8f029..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/FrameworkResourceManager.java
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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.ide.eclipse.common.resources;
-
-import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.CommonPlugin;
-
-import java.util.ArrayList;
-import java.util.Hashtable;
-import java.util.Map;
-
-/**
- * This is a communication between different plugins that don't know each other. It allows one
- * plugin to provide detailed information about the framework resources to another plugin.
- */
-public class FrameworkResourceManager {
-
- private static String[] sBooleanValues = new String[] {
- "true", //$NON-NLS-1$
- "false", //$NON-NLS-1$
- };
-
- private static FrameworkResourceManager sThis = new FrameworkResourceManager();
-
- private ArrayList<Runnable> mResourcesChangeListeners = new ArrayList<Runnable>();
-
- private Hashtable<String, String[]> mAttributeValues;
-
- private IResourceRepository mSystemResourceRepository;
-
- private ViewClassInfo[] mLayoutViewsInfo;
- private ViewClassInfo[] mLayoutGroupsInfo;
- private ViewClassInfo[] mPreferencesInfo;
- private ViewClassInfo[] mPreferenceGroupsInfo;
-
- private Map<String, DeclareStyleableInfo> mXmlMenuMap;
- private Map<String, DeclareStyleableInfo> mXmlSearchableMap;
- private Map<String, DeclareStyleableInfo> mManifestMap;
-
- /** Flags indicating whether we have some resources */
- private boolean mHasResources = false;
-
- private String mLayoutLibLocation;
-
- private String mFrameworkResourcesLocation;
-
- private Map<String, Map<String, Integer>> mEnumValueMap;
-
- private String mFrameworkFontsLocation;
-
- private String mDocBaseUrl;
-
- /**
- * Creates a new Framework Resource Manager.
- *
- * mAttributeValues is a map { key => list [ values ] }.
- * The key for the map is "(element-xml-name,attribute-namespace:attribute-xml-local-name)".
- * The attribute namespace prefix must be:
- * - "android" for AndroidConstants.NS_RESOURCES
- * - "xmlns" for the XMLNS URI.
- */
- private FrameworkResourceManager() {
- /* TODO Attempt to load those values from android.jar */
- mAttributeValues = new Hashtable<String, String[]>();
- mAttributeValues.put("(manifest,xmlns:android)", new String[] { //$NON-NLS-1$
- AndroidConstants.NS_RESOURCES
- });
- mAttributeValues.put("(permission,android:protectionLevel)", new String[] { //$NON-NLS-1$
- "application", //$NON-NLS-1$
- "system" //$NON-NLS-1$
- });
- mAttributeValues.put("(application,android:persistent)", new String[] { //$NON-NLS-1$
- "true", //$NON-NLS-1$
- "false", //$NON-NLS-1$
- });
- mAttributeValues.put("(activity,android:clearOnBackground)", sBooleanValues); //$NON-NLS-1$
- mAttributeValues.put("(activity,android:configChanges)", new String[] { //$NON-NLS-1$
- "fontScale", //$NON-NLS-1$
- "mcc", //$NON-NLS-1$
- "mnc", //$NON-NLS-1$
- "locale", //$NON-NLS-1$
- "touchscreen", //$NON-NLS-1$
- "keyboard", //$NON-NLS-1$
- "keyboardHidden", //$NON-NLS-1$
- "navigation", //$NON-NLS-1$
- "orientation", //$NON-NLS-1$
- });
- mAttributeValues.put("(activity,android:launchMode)", new String[] { //$NON-NLS-1$
- "multiple", //$NON-NLS-1$
- "singleTop", //$NON-NLS-1$
- "singleTask", //$NON-NLS-1$
- "singleInstance" //$NON-NLS-1$
- });
- mAttributeValues.put("(activity,android:stateNotNeeded)", sBooleanValues); //$NON-NLS-1$
- mAttributeValues.put("(provider,android:syncable)", sBooleanValues); //$NON-NLS-1$
- mAttributeValues.put("(provider,android:multiprocess)", sBooleanValues); //$NON-NLS-1$
- mAttributeValues.put("(instrumentation,android:functionalTest)", sBooleanValues); //$NON-NLS-1$
- mAttributeValues.put("(instrumentation,android:handleProfiling)", sBooleanValues); //$NON-NLS-1$
-
- }
-
- /**
- * Returns the {@link FrameworkResourceManager} instance.
- */
- public static FrameworkResourceManager getInstance() {
- return sThis;
- }
-
- /**
- * Sets the resources and notifies the listeners
- * @param documentationBaseUrl
- */
- public synchronized void setResources(IResourceRepository systemResourceRepository,
- ViewClassInfo[] layoutViewsInfo,
- ViewClassInfo[] layoutGroupsInfo,
- ViewClassInfo[] preferencesInfo,
- ViewClassInfo[] preferenceGroupsInfo,
- Map<String, DeclareStyleableInfo> xmlMenuMap,
- Map<String, DeclareStyleableInfo> xmlSearchableMap,
- Map<String, DeclareStyleableInfo> manifestMap,
- Map<String, Map<String, Integer>> enumValueMap,
- String[] permissionValues,
- String[] activityIntentActionValues,
- String[] broadcastIntentActionValues,
- String[] serviceIntentActionValues,
- String[] intentCategoryValues,
- String documentationBaseUrl) {
- mSystemResourceRepository = systemResourceRepository;
-
- mLayoutViewsInfo = layoutViewsInfo;
- mLayoutGroupsInfo = layoutGroupsInfo;
-
- mPreferencesInfo = preferencesInfo;
- mPreferenceGroupsInfo = preferenceGroupsInfo;
-
- mXmlMenuMap = xmlMenuMap;
- mXmlSearchableMap = xmlSearchableMap;
- mManifestMap = manifestMap;
- mEnumValueMap = enumValueMap;
- mDocBaseUrl = documentationBaseUrl;
-
- setPermissions(permissionValues);
- setIntentFilterActionsAndCategories(activityIntentActionValues, broadcastIntentActionValues,
- serviceIntentActionValues, intentCategoryValues);
-
- mHasResources = true;
-
- notifyFrameworkResourcesChangeListeners();
- }
-
- public synchronized IResourceRepository getSystemResources() {
- return mSystemResourceRepository;
- }
-
- public synchronized String[] getValues(String elementName, String attributeName) {
- String key = String.format("(%1$s,%2$s)", elementName, attributeName); //$NON-NLS-1$
- return mAttributeValues.get(key);
- }
-
- public synchronized String[] getValues(String elementName, String attributeName,
- String greatGrandParentElementName) {
- if (greatGrandParentElementName != null) {
- String key = String.format("(%1$s,%2$s,%3$s)", greatGrandParentElementName, //$NON-NLS-1$
- elementName, attributeName);
- String[] values = mAttributeValues.get(key);
- if (values != null) {
- return values;
- }
- }
-
- return getValues(elementName, attributeName);
- }
-
- public synchronized String[] getValues(String key) {
- return mAttributeValues.get(key);
- }
-
- public synchronized ViewClassInfo[] getLayoutViewsInfo() {
- return mLayoutViewsInfo;
- }
-
- public synchronized ViewClassInfo[] getLayoutGroupsInfo() {
- return mLayoutGroupsInfo;
- }
-
- public synchronized ViewClassInfo[] getPreferencesInfo() {
- return mPreferencesInfo;
- }
-
- public synchronized ViewClassInfo[] getPreferenceGroupsInfo() {
- return mPreferenceGroupsInfo;
- }
-
- public synchronized Map<String, DeclareStyleableInfo> getXmlMenuDefinitions() {
- return mXmlMenuMap;
- }
-
- public synchronized Map<String, DeclareStyleableInfo> getXmlSearchableDefinitions() {
- return mXmlSearchableMap;
- }
-
- public synchronized Map<String, DeclareStyleableInfo> getManifestDefinitions() {
- return mManifestMap;
- }
-
- public String getDocumentationBaseUrl() {
- return mDocBaseUrl == null ? AndroidConstants.CODESITE_BASE_URL : mDocBaseUrl;
- }
-
- /**
- * Sets the permission values
- * @param permissionValues the list of permissions
- */
- private void setPermissions(String[] permissionValues) {
- setValues("(uses-permission,android:name)", permissionValues); //$NON-NLS-1$
- setValues("(application,android:permission)", permissionValues); //$NON-NLS-1$
- setValues("(activity,android:permission)", permissionValues); //$NON-NLS-1$
- setValues("(receiver,android:permission)", permissionValues); //$NON-NLS-1$
- setValues("(service,android:permission)", permissionValues); //$NON-NLS-1$
- setValues("(provider,android:permission)", permissionValues); //$NON-NLS-1$
- }
-
- private void setIntentFilterActionsAndCategories(String[] activityIntentActions,
- String[] broadcastIntentActions, String[] serviceIntentActions,
- String[] intentCategoryValues) {
- setValues("(activity,action,android:name)", activityIntentActions); //$NON-NLS-1$
- setValues("(receiver,action,android:name)", broadcastIntentActions); //$NON-NLS-1$
- setValues("(service,action,android:name)", serviceIntentActions); //$NON-NLS-1$
- setValues("(category,android:name)", intentCategoryValues); //$NON-NLS-1$
- }
-
- /**
- * Sets a (name, values) pair in the hash map.
- * <p/>
- * If the name is already present in the map, it is first removed.
- * @param name the name associated with the values.
- * @param values The values to add.
- */
- private void setValues(String name, String[] values) {
- mAttributeValues.remove(name);
- mAttributeValues.put(name, values);
- }
-
-
- /**
- * Called by the ADT plugin when the SDK path has changed.
- * This stores the path locally and then notifies all attached listeners.
- */
- private void notifyFrameworkResourcesChangeListeners() {
- for (Runnable listener : mResourcesChangeListeners) {
- try {
- listener.run();
- } catch (Exception e) {
- CommonPlugin.log(e, "IPathChangedListener failed."); //$NON-NLS-1$
- }
- }
- }
-
- /** Adds a new listener that listens to framework resources changes.
- * <p/>If resources have already been set, then the listener is automatically notified. */
- public synchronized void addFrameworkResourcesChangeListener(Runnable listener) {
- if (listener != null && mResourcesChangeListeners.indexOf(listener) == -1) {
- mResourcesChangeListeners.add(listener);
-
- if (mHasResources) {
- listener.run();
- }
- }
- }
-
- /** Removes a framework resources changes listener.
- * <p/>Safe to call with null or with the same value. */
- public synchronized void removeFrameworkResourcesChangeListener(Runnable listener) {
- mResourcesChangeListeners.remove(listener);
- }
-
- public void setLayoutLibLocation(String osLocation) {
- mLayoutLibLocation = osLocation;
- }
-
- public String getLayoutLibLocation() {
- return mLayoutLibLocation;
- }
-
- public void setFrameworkResourcesLocation(String osLocation) {
- mFrameworkResourcesLocation = osLocation;
- }
-
- public String getFrameworkResourcesLocation() {
- return mFrameworkResourcesLocation;
- }
-
- public Map<String, Map<String, Integer>> getEnumValueMap() {
- return mEnumValueMap;
- }
-
- public void setFrameworkFontLocation(String osLocation) {
- mFrameworkFontsLocation = osLocation;
- }
-
- public String getFrameworkFontLocation() {
- return mFrameworkFontsLocation;
- }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF b/tools/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF
index 2f315c5..09b8085 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
Bundle-ManifestVersion: 2
Bundle-Name: Dalvik Debug Monitor Service
Bundle-SymbolicName: com.android.ide.eclipse.ddms;singleton:=true
-Bundle-Version: 0.8.1.qualifier
+Bundle-Version: 0.9.0.qualifier
Bundle-Activator: com.android.ide.eclipse.ddms.DdmsPlugin
Bundle-Vendor: The Android Open Source Project
Bundle-Localization: plugin
@@ -10,11 +10,13 @@
org.eclipse.core.runtime,
org.eclipse.ui.console
Eclipse-LazyStart: true
-Export-Package: com.android.ide.eclipse.ddms,
- com.android.ide.eclipse.ddms.views,
- com.android.ddmlib,
+Export-Package: com.android.ddmlib,
+ com.android.ddmlib.log,
+ com.android.ddmlib.testrunner,
com.android.ddmuilib,
- com.android.ddmuilib.console
+ com.android.ddmuilib.console,
+ com.android.ide.eclipse.ddms,
+ com.android.ide.eclipse.ddms.views
Bundle-ClassPath: libs/jcommon-1.0.12.jar,
libs/jfreechart-1.0.9.jar,
libs/jfreechart-1.0.9-swt.jar,
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/.classpath b/tools/eclipse/plugins/com.android.ide.eclipse.editors/.classpath
deleted file mode 100644
index 66dbeb3..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/.classpath
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins">
- <accessrules>
- <accessrule kind="accessible" pattern="org/eclipse/wst/**/internal/**"/>
- </accessrules>
- </classpathentry>
- <classpathentry kind="lib" path="kxml2-2.3.0.jar"/>
- <classpathentry kind="lib" path="layoutlib_api.jar"/>
- <classpathentry kind="lib" path="ninepatch.jar"/>
- <classpathentry kind="lib" path="layoutlib_utils.jar"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/.project b/tools/eclipse/plugins/com.android.ide.eclipse.editors/.project
deleted file mode 100644
index 292c698..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/.project
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>editors</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.ManifestBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.SchemaBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.pde.PluginNature</nature>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
-</projectDescription>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/META-INF/MANIFEST.MF b/tools/eclipse/plugins/com.android.ide.eclipse.editors/META-INF/MANIFEST.MF
deleted file mode 100644
index 0bfaff9..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,56 +0,0 @@
-Manifest-Version: 1.0
-Bundle-ManifestVersion: 2
-Bundle-Name: Android Editors
-Bundle-SymbolicName: com.android.ide.eclipse.editors;singleton:=true
-Bundle-Version: 0.8.1.qualifier
-Bundle-Activator: com.android.ide.eclipse.editors.EditorsPlugin
-Bundle-Vendor: The Android Open Source Project
-Require-Bundle: com.android.ide.eclipse.common,
- org.eclipse.ui,
- org.eclipse.core.runtime,
- org.eclipse.core.resources,
- org.eclipse.ui.editors,
- org.eclipse.jface.text,
- org.eclipse.ui.ide,
- org.eclipse.wst.sse.ui,
- org.eclipse.wst.xml.ui,
- org.eclipse.wst.xml.core,
- org.eclipse.wst.sse.core,
- org.eclipse.ui.forms,
- org.eclipse.jdt.core,
- org.eclipse.ui.browser,
- org.eclipse.jdt.ui,
- org.eclipse.gef,
- org.eclipse.ui.views,
- org.eclipse.ui.console
-Eclipse-LazyStart: true
-Export-Package: com.android.ide.eclipse.editors;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.descriptors;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.layout;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.layout.descriptors;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.layout.parts;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.layout.uimodel;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.manifest;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.manifest.descriptors;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.manifest.model;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.manifest.pages;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.menu;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.menu.descriptors;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.resources;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.resources.configurations;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.resources.descriptors;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.resources.explorer;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.resources.manager;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.resources.manager.files;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.resources.uimodel;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.ui;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.ui.tree;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.uimodel;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.wizards;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.xml;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.xml.descriptors;x-friends:="com.android.ide.eclipse.tests"
-Bundle-ClassPath: kxml2-2.3.0.jar,
- .,
- layoutlib_api.jar,
- ninepatch.jar,
- layoutlib_utils.jar
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/MODULE_LICENSE_EPL b/tools/eclipse/plugins/com.android.ide.eclipse.editors/MODULE_LICENSE_EPL
deleted file mode 100644
index e69de29..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/MODULE_LICENSE_EPL
+++ /dev/null
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/NOTICE b/tools/eclipse/plugins/com.android.ide.eclipse.editors/NOTICE
deleted file mode 100644
index 49c101d..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/NOTICE
+++ /dev/null
@@ -1,224 +0,0 @@
-*Eclipse Public License - v 1.0*
-
-THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
-PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF
-THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
-
-*1. DEFINITIONS*
-
-"Contribution" means:
-
-a) in the case of the initial Contributor, the initial code and
-documentation distributed under this Agreement, and
-b) in the case of each subsequent Contributor:
-
-i) changes to the Program, and
-
-ii) additions to the Program;
-
-where such changes and/or additions to the Program originate from and
-are distributed by that particular Contributor. A Contribution
-'originates' from a Contributor if it was added to the Program by such
-Contributor itself or anyone acting on such Contributor's behalf.
-Contributions do not include additions to the Program which: (i) are
-separate modules of software distributed in conjunction with the Program
-under their own license agreement, and (ii) are not derivative works of
-the Program.
-
-"Contributor" means any person or entity that distributes the Program.
-
-"Licensed Patents " mean patent claims licensable by a Contributor which
-are necessarily infringed by the use or sale of its Contribution alone
-or when combined with the Program.
-
-"Program" means the Contributions distributed in accordance with this
-Agreement.
-
-"Recipient" means anyone who receives the Program under this Agreement,
-including all Contributors.
-
-*2. GRANT OF RIGHTS*
-
-a) Subject to the terms of this Agreement, each Contributor hereby
-grants Recipient a non-exclusive, worldwide, royalty-free copyright
-license to reproduce, prepare derivative works of, publicly display,
-publicly perform, distribute and sublicense the Contribution of such
-Contributor, if any, and such derivative works, in source code and
-object code form.
-
-b) Subject to the terms of this Agreement, each Contributor hereby
-grants Recipient a non-exclusive, worldwide, royalty-free patent license
-under Licensed Patents to make, use, sell, offer to sell, import and
-otherwise transfer the Contribution of such Contributor, if any, in
-source code and object code form. This patent license shall apply to the
-combination of the Contribution and the Program if, at the time the
-Contribution is added by the Contributor, such addition of the
-Contribution causes such combination to be covered by the Licensed
-Patents. The patent license shall not apply to any other combinations
-which include the Contribution. No hardware per se is licensed hereunder.
-
-c) Recipient understands that although each Contributor grants the
-licenses to its Contributions set forth herein, no assurances are
-provided by any Contributor that the Program does not infringe the
-patent or other intellectual property rights of any other entity. Each
-Contributor disclaims any liability to Recipient for claims brought by
-any other entity based on infringement of intellectual property rights
-or otherwise. As a condition to exercising the rights and licenses
-granted hereunder, each Recipient hereby assumes sole responsibility to
-secure any other intellectual property rights needed, if any. For
-example, if a third party patent license is required to allow Recipient
-to distribute the Program, it is Recipient's responsibility to acquire
-that license before distributing the Program.
-
-d) Each Contributor represents that to its knowledge it has sufficient
-copyright rights in its Contribution, if any, to grant the copyright
-license set forth in this Agreement.
-
-*3. REQUIREMENTS*
-
-A Contributor may choose to distribute the Program in object code form
-under its own license agreement, provided that:
-
-a) it complies with the terms and conditions of this Agreement; and
-
-b) its license agreement:
-
-i) effectively disclaims on behalf of all Contributors all warranties
-and conditions, express and implied, including warranties or conditions
-of title and non-infringement, and implied warranties or conditions of
-merchantability and fitness for a particular purpose;
-
-ii) effectively excludes on behalf of all Contributors all liability for
-damages, including direct, indirect, special, incidental and
-consequential damages, such as lost profits;
-
-iii) states that any provisions which differ from this Agreement are
-offered by that Contributor alone and not by any other party; and
-
-iv) states that source code for the Program is available from such
-Contributor, and informs licensees how to obtain it in a reasonable
-manner on or through a medium customarily used for software exchange.
-
-When the Program is made available in source code form:
-
-a) it must be made available under this Agreement; and
-
-b) a copy of this Agreement must be included with each copy of the Program.
-
-Contributors may not remove or alter any copyright notices contained
-within the Program.
-
-Each Contributor must identify itself as the originator of its
-Contribution, if any, in a manner that reasonably allows subsequent
-Recipients to identify the originator of the Contribution.
-
-*4. COMMERCIAL DISTRIBUTION*
-
-Commercial distributors of software may accept certain responsibilities
-with respect to end users, business partners and the like. While this
-license is intended to facilitate the commercial use of the Program, the
-Contributor who includes the Program in a commercial product offering
-should do so in a manner which does not create potential liability for
-other Contributors. Therefore, if a Contributor includes the Program in
-a commercial product offering, such Contributor ("Commercial
-Contributor") hereby agrees to defend and indemnify every other
-Contributor ("Indemnified Contributor") against any losses, damages and
-costs (collectively "Losses") arising from claims, lawsuits and other
-legal actions brought by a third party against the Indemnified
-Contributor to the extent caused by the acts or omissions of such
-Commercial Contributor in connection with its distribution of the
-Program in a commercial product offering. The obligations in this
-section do not apply to any claims or Losses relating to any actual or
-alleged intellectual property infringement. In order to qualify, an
-Indemnified Contributor must: a) promptly notify the Commercial
-Contributor in writing of such claim, and b) allow the Commercial
-Contributor to control, and cooperate with the Commercial Contributor
-in, the defense and any related settlement negotiations. The Indemnified
-Contributor may participate in any such claim at its own expense.
-
-For example, a Contributor might include the Program in a commercial
-product offering, Product X. That Contributor is then a Commercial
-Contributor. If that Commercial Contributor then makes performance
-claims, or offers warranties related to Product X, those performance
-claims and warranties are such Commercial Contributor's responsibility
-alone. Under this section, the Commercial Contributor would have to
-defend claims against the other Contributors related to those
-performance claims and warranties, and if a court requires any other
-Contributor to pay any damages as a result, the Commercial Contributor
-must pay those damages.
-
-*5. NO WARRANTY*
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED
-ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
-EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES
-OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR
-A PARTICULAR PURPOSE. Each Recipient is solely responsible for
-determining the appropriateness of using and distributing the Program
-and assumes all risks associated with its exercise of rights under this
-Agreement , including but not limited to the risks and costs of program
-errors, compliance with applicable laws, damage to or loss of data,
-programs or equipment, and unavailability or interruption of operations.
-
-*6. DISCLAIMER OF LIABILITY*
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
-ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
-WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
-DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
-HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-*7. GENERAL*
-
-If any provision of this Agreement is invalid or unenforceable under
-applicable law, it shall not affect the validity or enforceability of
-the remainder of the terms of this Agreement, and without further action
-by the parties hereto, such provision shall be reformed to the minimum
-extent necessary to make such provision valid and enforceable.
-
-If Recipient institutes patent litigation against any entity (including
-a cross-claim or counterclaim in a lawsuit) alleging that the Program
-itself (excluding combinations of the Program with other software or
-hardware) infringes such Recipient's patent(s), then such Recipient's
-rights granted under Section 2(b) shall terminate as of the date such
-litigation is filed.
-
-All Recipient's rights under this Agreement shall terminate if it fails
-to comply with any of the material terms or conditions of this Agreement
-and does not cure such failure in a reasonable period of time after
-becoming aware of such noncompliance. If all Recipient's rights under
-this Agreement terminate, Recipient agrees to cease use and distribution
-of the Program as soon as reasonably practicable. However, Recipient's
-obligations under this Agreement and any licenses granted by Recipient
-relating to the Program shall continue and survive.
-
-Everyone is permitted to copy and distribute copies of this Agreement,
-but in order to avoid inconsistency the Agreement is copyrighted and may
-only be modified in the following manner. The Agreement Steward reserves
-the right to publish new versions (including revisions) of this
-Agreement from time to time. No one other than the Agreement Steward has
-the right to modify this Agreement. The Eclipse Foundation is the
-initial Agreement Steward. The Eclipse Foundation may assign the
-responsibility to serve as the Agreement Steward to a suitable separate
-entity. Each new version of the Agreement will be given a distinguishing
-version number. The Program (including Contributions) may always be
-distributed subject to the version of the Agreement under which it was
-received. In addition, after a new version of the Agreement is
-published, Contributor may elect to distribute the Program (including
-its Contributions) under the new version. Except as expressly stated in
-Sections 2(a) and 2(b) above, Recipient receives no rights or licenses
-to the intellectual property of any Contributor under this Agreement,
-whether expressly, by implication, estoppel or otherwise. All rights in
-the Program not expressly granted under this Agreement are reserved.
-
-This Agreement is governed by the laws of the State of New York and the
-intellectual property laws of the United States of America. No party to
-this Agreement will bring a legal action under this Agreement more than
-one year after the cause of action arose. Each party waives its rights
-to a jury trial in any resulting litigation.
-
-
-
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/build.properties b/tools/eclipse/plugins/com.android.ide.eclipse.editors/build.properties
deleted file mode 100644
index 0a7bc7d..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/build.properties
+++ /dev/null
@@ -1,10 +0,0 @@
-source.. = src/
-output.. = bin/
-bin.includes = META-INF/,\
- .,\
- plugin.xml,\
- icons/,\
- layoutlib_api.jar,\
- kxml2-2.3.0.jar,\
- ninepatch.jar,\
- layoutlib_utils.jar
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/android.png b/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/android.png
deleted file mode 100644
index 3779d4d..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/android.png
+++ /dev/null
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/android_large.png b/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/android_large.png
deleted file mode 100644
index 64e3601..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/android_large.png
+++ /dev/null
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/region.png b/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/region.png
deleted file mode 100644
index 9cfb53f..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/region.png
+++ /dev/null
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/world.png b/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/world.png
deleted file mode 100644
index afdc16c..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/world.png
+++ /dev/null
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/plugin.xml b/tools/eclipse/plugins/com.android.ide.eclipse.editors/plugin.xml
deleted file mode 100644
index 2678a5d..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/plugin.xml
+++ /dev/null
@@ -1,107 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?eclipse version="3.2"?>
-<plugin>
- <extension
- point="org.eclipse.ui.editors">
- <editor
- class="com.android.ide.eclipse.editors.manifest.ManifestEditor"
- default="true"
- filenames="AndroidManifest.xml"
- icon="icons/android.png"
- id="com.android.ide.eclipse.editors.manifest.ManifestEditor"
- name="Android Manifest Editor">
- </editor>
- <editor
- class="com.android.ide.eclipse.editors.resources.ResourcesEditor"
- default="false"
- extensions="xml"
- icon="icons/android.png"
- id="com.android.ide.eclipse.editors.resources.ResourcesEditor"
- name="Android Resource Editor">
- </editor>
- <editor
- class="com.android.ide.eclipse.editors.layout.LayoutEditor"
- default="false"
- extensions="xml"
- icon="icons/android.png"
- id="com.android.ide.eclipse.editors.layout.LayoutEditor"
- matchingStrategy="com.android.ide.eclipse.editors.layout.MatchingStrategy"
- name="Android Layout Editor">
- </editor>
- <editor
- class="com.android.ide.eclipse.editors.menu.MenuEditor"
- default="false"
- extensions="xml"
- icon="icons/android.png"
- id="com.android.ide.eclipse.editors.menu.MenuEditor"
- name="Android Menu Editor">
- </editor>
- <editor
- class="com.android.ide.eclipse.editors.xml.XmlEditor"
- default="false"
- extensions="xml"
- icon="icons/android.png"
- id="com.android.ide.eclipse.editors.xml.XmlEditor"
- name="Android Xml Resources Editor">
- </editor>
- </extension>
- <extension
- point="org.eclipse.wst.sse.ui.editorConfiguration">
- <sourceViewerConfiguration
- class="com.android.ide.eclipse.editors.manifest.ManifestSourceViewerConfig"
- target="com.android.ide.eclipse.editors.manifest.ManifestEditor">
- </sourceViewerConfiguration>
- <sourceViewerConfiguration
- class="com.android.ide.eclipse.editors.resources.ResourcesSourceViewerConfig"
- target="com.android.ide.eclipse.editors.resources.ResourcesEditor">
- </sourceViewerConfiguration>
- <sourceViewerConfiguration
- class="com.android.ide.eclipse.editors.layout.LayoutSourceViewerConfig"
- target="com.android.ide.eclipse.editors.layout.LayoutEditor">
- </sourceViewerConfiguration>
- <sourceViewerConfiguration
- class="com.android.ide.eclipse.editors.menu.MenuSourceViewerConfig"
- target="com.android.ide.eclipse.editors.menu.MenuEditor">
- </sourceViewerConfiguration>
- <sourceViewerConfiguration
- class="com.android.ide.eclipse.editors.xml.XmlSourceViewerConfig"
- target="com.android.ide.eclipse.editors.xml.XmlEditor">
- </sourceViewerConfiguration>
- </extension>
- <extension
- point="org.eclipse.ui.views">
- <view
- allowMultiple="false"
- category="com.android.ide.eclipse.ddms.views.category"
- class="com.android.ide.eclipse.editors.resources.explorer.ResourceExplorerView"
- icon="icons/android.png"
- id="com.android.ide.eclipse.editors.resources.explorer.ResourceExplorerView"
- name="Resource Explorer">
- </view>
- </extension>
- <extension
- point="org.eclipse.ui.newWizards">
- <wizard
- canFinishEarly="false"
- category="com.android.ide.eclipse.wizards.category"
- class="com.android.ide.eclipse.editors.wizards.NewXmlFileWizard"
- finalPerspective="org.eclipse.jdt.ui.JavaPerspective"
- hasPages="true"
- icon="icons/android.png"
- id="com.android.ide.eclipse.editors.wizards.NewXmlFileWizard"
- name="Android XML File"
- preferredPerspectives="org.eclipse.jdt.ui.JavaPerspective"
- project="false">
- </wizard>
- </extension>
- <extension
- point="org.eclipse.ui.perspectiveExtensions">
- <perspectiveExtension
- targetID="org.eclipse.jdt.ui.JavaPerspective">
- <newWizardShortcut
- id="com.android.ide.eclipse.editors.wizards.NewXmlFileWizard">
- </newWizardShortcut>
- </perspectiveExtension>
- </extension>
-
-</plugin>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/EditorsPlugin.java b/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/EditorsPlugin.java
deleted file mode 100644
index 354276a..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/EditorsPlugin.java
+++ /dev/null
@@ -1,672 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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.ide.eclipse.editors;
-
-import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.CommonPlugin;
-import com.android.ide.eclipse.common.SdkStatsHelper;
-import com.android.ide.eclipse.common.StreamHelper;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
-import com.android.ide.eclipse.editors.EditorsPlugin.LayoutBridge.LoadStatus;
-import com.android.ide.eclipse.editors.layout.LayoutEditor;
-import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
-import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
-import com.android.ide.eclipse.editors.menu.MenuEditor;
-import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors;
-import com.android.ide.eclipse.editors.resources.ResourcesEditor;
-import com.android.ide.eclipse.editors.resources.manager.ProjectResources;
-import com.android.ide.eclipse.editors.resources.manager.ResourceFolder;
-import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType;
-import com.android.ide.eclipse.editors.resources.manager.ResourceManager;
-import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor;
-import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IFileListener;
-import com.android.ide.eclipse.editors.xml.XmlEditor;
-import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
-import com.android.layoutlib.api.ILayoutBridge;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IFolder;
-import org.eclipse.core.resources.IMarkerDelta;
-import org.eclipse.core.resources.IResourceDelta;
-import org.eclipse.core.resources.IWorkspace;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.QualifiedName;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.SubMonitor;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.IEditorDescriptor;
-import org.eclipse.ui.IEditorPart;
-import org.eclipse.ui.IWorkbench;
-import org.eclipse.ui.IWorkbenchPage;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.console.MessageConsole;
-import org.eclipse.ui.console.MessageConsoleStream;
-import org.eclipse.ui.ide.IDE;
-import org.eclipse.ui.part.FileEditorInput;
-import org.eclipse.ui.plugin.AbstractUIPlugin;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.Version;
-
-import java.io.File;
-import java.io.OutputStream;
-import java.lang.reflect.Constructor;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.ArrayList;
-
-/**
- * The activator class controls the plug-in life cycle
- */
-public class EditorsPlugin extends AbstractUIPlugin {
- // The shared instance
- private static EditorsPlugin sPlugin;
-
- private static Image sAndroidLogo;
- private static ImageDescriptor sAndroidLogoDesc;
-
- private ResourceMonitor mResourceMonitor;
- private SdkPathChangedListener mSdkPathChangedListener;
- private ArrayList<Runnable> mResourceRefreshListener = new ArrayList<Runnable>();
-
- private MessageConsoleStream mAndroidConsoleStream;
- /** Stream to write error messages to the android console */
- private MessageConsoleStream mAndroidConsoleErrorStream;
-
- public final static class LayoutBridge {
- public enum LoadStatus { LOADING, LOADED, FAILED }
-
- /** Link to the layout bridge */
- public ILayoutBridge bridge;
-
- public LoadStatus status = LoadStatus.LOADING;
- }
-
- private final LayoutBridge mLayoutBridge = new LayoutBridge();
-
- private boolean mLayoutBridgeInit;
-
- private ClassLoader mBridgeClassLoader;
-
- private Color mRed;
-
-
- /**
- * The constructor
- */
- public EditorsPlugin() {
- }
-
- /**
- * The <code>AbstractUIPlugin</code> implementation of this <code>Plugin</code>
- * method refreshes the plug-in actions. Subclasses may extend this method,
- * but must send super <b>first</b>.
- * {@inheritDoc}
- *
- * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
- */
- @Override
- public void start(BundleContext context) throws Exception {
- super.start(context);
- sPlugin = this;
- sAndroidLogoDesc = imageDescriptorFromPlugin(AndroidConstants.EDITORS_PLUGIN_ID,
- "/icons/android.png"); //$NON-NLS-1$
- sAndroidLogo = sAndroidLogoDesc.createImage();
-
- // get the stream to write in the android console.
- MessageConsole androidConsole = CommonPlugin.getDefault().getAndroidConsole();
- mAndroidConsoleStream = androidConsole.newMessageStream();
-
- mAndroidConsoleErrorStream = androidConsole.newMessageStream();
- mRed = new Color(getDisplay(), 0xFF, 0x00, 0x00);
-
- // because this can be run, in some cases, by a non ui thread, and beccause
- // changing the console properties update the ui, we need to make this change
- // in the ui thread.
- getDisplay().asyncExec(new Runnable() {
- public void run() {
- mAndroidConsoleErrorStream.setColor(mRed);
- }
- });
-
- // Add a resource listener to handle compiled resources.
- IWorkspace ws = ResourcesPlugin.getWorkspace();
- mResourceMonitor = ResourceMonitor.startMonitoring(ws);
-
- if (mResourceMonitor != null) {
- setupDefaultEditor(mResourceMonitor);
- ResourceManager.setup(mResourceMonitor);
- }
-
- // Setup the sdk location changed listener and invoke it the first time
- mSdkPathChangedListener = new SdkPathChangedListener();
- FrameworkResourceManager.getInstance().addFrameworkResourcesChangeListener(
- mSdkPathChangedListener);
-
- // ping the usage server
- pingUsageServer();
- }
-
- /**
- * The <code>AbstractUIPlugin</code> implementation of this <code>Plugin</code>
- * method saves this plug-in's preference and dialog stores and shuts down
- * its image registry (if they are in use). Subclasses may extend this
- * method, but must send super <b>last</b>. A try-finally statement should
- * be used where necessary to ensure that <code>super.shutdown()</code> is
- * always done.
- *
- * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
- */
- @Override
- public void stop(BundleContext context) throws Exception {
- sPlugin = null;
- sAndroidLogo.dispose();
-
- IconFactory.getInstance().Dispose();
-
- // Remove the resource listener that handles compiled resources.
- IWorkspace ws = ResourcesPlugin.getWorkspace();
- ResourceMonitor.stopMonitoring(ws);
-
- FrameworkResourceManager.getInstance().removeFrameworkResourcesChangeListener(
- mSdkPathChangedListener);
- mSdkPathChangedListener = null;
-
- mRed.dispose();
-
- super.stop(context);
- }
-
- /**
- * Returns the shared instance
- *
- * @return the shared instance
- */
- public static EditorsPlugin getDefault() {
- return sPlugin;
- }
-
- /**
- * Returns an Image for the small Android logo.
- *
- * Callers should not dispose it.
- */
- public static Image getAndroidLogo() {
- return sAndroidLogo;
- }
-
- /**
- * Returns an {@link ImageDescriptor} for the small Android logo.
- *
- * Callers should not dispose it.
- */
- public static ImageDescriptor getAndroidLogoDesc() {
- return sAndroidLogoDesc;
- }
-
- /**
- * Logs a message to the default Eclipse log.
- *
- * @param severity One of IStatus' severity codes: OK, ERROR, INFO, WARNING or CANCEL.
- * @param format The format string, like for String.format().
- * @param args The arguments for the format string, like for String.format().
- */
- public static void log(int severity, String format, Object ... args) {
- String message = String.format(format, args);
- Status status = new Status(severity, AndroidConstants.EDITORS_PLUGIN_ID, message);
- getDefault().getLog().log(status);
- }
-
- /**
- * Logs an exception to the default Eclipse log.
- * <p/>
- * The status severity is always set to ERROR.
- *
- * @param exception The exception to log. Its call trace will be recorded.
- * @param format The format string, like for String.format().
- * @param args The arguments for the format string, like for String.format().
- */
- public static void log(Throwable exception, String format, Object ... args) {
- String message = String.format(format, args);
- Status status = new Status(IStatus.ERROR, AndroidConstants.EDITORS_PLUGIN_ID,
- message, exception);
- getDefault().getLog().log(status);
- }
-
- /**
- * Returns the ResourceMonitor object.
- */
- public ResourceMonitor getResourceMonitor() {
- return mResourceMonitor;
- }
-
-
- /**
- * Sets up the editor to register default editors for resource files when needed.
- *
- * This is called by the {@link EditorsPlugin} during initialization.
- *
- * @param monitor The main Resource Monitor object.
- */
- public void setupDefaultEditor(ResourceMonitor monitor) {
- monitor.addFileListener(new IFileListener() {
-
- private static final String UNKNOWN_EDITOR = "unknown-editor"; //$NON-NLS-1$
-
- /* (non-Javadoc)
- * Sent when a file changed.
- * @param file The file that changed.
- * @param markerDeltas The marker deltas for the file.
- * @param kind The change kind. This is equivalent to
- * {@link IResourceDelta#accept(IResourceDeltaVisitor)}
- *
- * @see IFileListener#fileChanged
- */
- public void fileChanged(IFile file, IMarkerDelta[] markerDeltas, int kind) {
- if (AndroidConstants.EXT_XML.equals(file.getFileExtension())) {
- // The resources files must have a file path similar to
- // project/res/.../*.xml
- // There is no support for sub folders, so the segment count must be 4
- if (file.getFullPath().segmentCount() == 4) {
- // check if we are inside the res folder.
- String segment = file.getFullPath().segment(1);
- if (segment.equalsIgnoreCase(AndroidConstants.FD_RESOURCES)) {
- // we are inside a res/ folder, get the actual ResourceFolder
- ProjectResources resources = ResourceManager.getInstance().
- getProjectResources(file.getProject());
-
- // This happens when importing old Android projects in Eclipse
- // that lack the container (probably because resources fail to build
- // properly.)
- if (resources == null) {
- log(IStatus.INFO,
- "getProjectResources failed for path %1$s in project %2$s", //$NON-NLS-1$
- file.getFullPath().toOSString(),
- file.getProject().getName());
- return;
- }
-
- ResourceFolder resFolder = resources.getResourceFolder(
- (IFolder)file.getParent());
-
- if (resFolder != null) {
- if (kind == IResourceDelta.ADDED) {
- resourceAdded(file, resFolder.getType());
- } else if (kind == IResourceDelta.CHANGED) {
- resourceChanged(file, resFolder.getType());
- }
- } else {
- // if the res folder is null, this means the name is invalid,
- // in this case we remove whatever android editors that was set
- // as the default editor.
- IEditorDescriptor desc = IDE.getDefaultEditor(file);
- String editorId = desc.getId();
- if (editorId.startsWith(AndroidConstants.EDITORS_PLUGIN_ID)) {
- // reset the default editor.
- IDE.setDefaultEditor(file, null);
- }
- }
- }
- }
- }
- }
-
- private void resourceAdded(IFile file, ResourceFolderType type) {
- // set the default editor based on the type.
- if (type == ResourceFolderType.LAYOUT) {
- IDE.setDefaultEditor(file, LayoutEditor.ID);
- } else if (type == ResourceFolderType.DRAWABLE
- || type == ResourceFolderType.VALUES) {
- IDE.setDefaultEditor(file, ResourcesEditor.ID);
- } else if (type == ResourceFolderType.MENU) {
- IDE.setDefaultEditor(file, MenuEditor.ID);
- } else if (type == ResourceFolderType.XML) {
- if (XmlEditor.canHandleFile(file)) {
- IDE.setDefaultEditor(file, XmlEditor.ID);
- } else {
- // set a property to determine later if the XML can be handled
- QualifiedName qname = new QualifiedName(
- AndroidConstants.EDITORS_PLUGIN_ID,
- UNKNOWN_EDITOR);
- try {
- file.setPersistentProperty(qname, "1");
- } catch (CoreException e) {
- // pass
- }
- }
- }
- }
-
- private void resourceChanged(IFile file, ResourceFolderType type) {
- if (type == ResourceFolderType.XML) {
- IEditorDescriptor ed = IDE.getDefaultEditor(file);
- if (ed == null || ed.getId() != XmlEditor.ID) {
- QualifiedName qname = new QualifiedName(
- AndroidConstants.EDITORS_PLUGIN_ID,
- UNKNOWN_EDITOR);
- String prop = null;
- try {
- prop = file.getPersistentProperty(qname);
- } catch (CoreException e) {
- // pass
- }
- if (prop != null && XmlEditor.canHandleFile(file)) {
- try {
- // remove the property & set editor
- file.setPersistentProperty(qname, null);
- IWorkbenchPage page = PlatformUI.getWorkbench().
- getActiveWorkbenchWindow().getActivePage();
-
- IEditorPart oldEditor = page.findEditor(new FileEditorInput(file));
- if (oldEditor != null &&
- CommonPlugin.displayPrompt("Android XML Editor",
- String.format("The file you just saved as been recognized as a file that could be better handled using the Android XML Editor. Do you want to edit '%1$s' using the Android XML editor instead?",
- file.getFullPath()))) {
- IDE.setDefaultEditor(file, XmlEditor.ID);
- IEditorPart newEditor = page.openEditor(
- new FileEditorInput(file),
- XmlEditor.ID,
- true, /* activate */
- IWorkbenchPage.MATCH_NONE);
-
- if (newEditor != null) {
- page.closeEditor(oldEditor, true /* save */);
- }
- }
- } catch (CoreException e) {
- // setPersistentProperty or page.openEditor may have failed
- }
- }
- }
- }
- }
-
- }, IResourceDelta.ADDED | IResourceDelta.CHANGED);
- }
-
- /**
- * Respond to notifications from the resource manager than the SDK resources have been updated.
- * It gets the new resources from the {@link FrameworkResourceManager} and then try to update
- * the layout descriptors from the new layout data.
- */
- private class SdkPathChangedListener implements Runnable {
- public void run() {
-
- // Perform the update in a thread (here an Eclipse runtime job)
- // since this should never block the caller (especially the start method)
- new Job("Editors: Load Framework Resource Parser") {
-
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- try {
- SubMonitor progress = SubMonitor.convert(monitor, "Update Description",
- 60);
-
- FrameworkResourceManager resourceManager = FrameworkResourceManager.getInstance();
-
- AndroidManifestDescriptors.updateDescriptors(
- resourceManager.getManifestDefinitions());
- progress.worked(10);
-
- if (progress.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
-
- LayoutDescriptors.getInstance().updateDescriptors(
- resourceManager.getLayoutViewsInfo(),
- resourceManager.getLayoutGroupsInfo());
- progress.worked(10);
-
- if (progress.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
-
- MenuDescriptors.getInstance().updateDescriptors(
- resourceManager.getXmlMenuDefinitions());
- progress.worked(10);
-
- if (progress.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
-
- XmlDescriptors.getInstance().updateDescriptors(
- resourceManager.getXmlSearchableDefinitions(),
- resourceManager.getPreferencesInfo(),
- resourceManager.getPreferenceGroupsInfo());
- progress.worked(10);
-
- // load the layout lib bridge.
- if (System.getenv("ANDROID_DISABLE_LAYOUT") == null) {
- loadLayoutBridge();
- FrameworkResourceManager frMgr = FrameworkResourceManager.getInstance();
- ResourceManager rMgr = ResourceManager.getInstance();
- rMgr.loadFrameworkResources(frMgr.getFrameworkResourcesLocation());
- }
- progress.worked(10);
-
- // Notify resource changed listeners
- progress.subTask("Refresh UI");
- progress.setWorkRemaining(mResourceRefreshListener.size());
-
- // Clone the list before iterating, to avoid Concurrent Modification
- // exceptions
- @SuppressWarnings("unchecked")
- ArrayList<Runnable> listeners = (ArrayList<Runnable>)
- mResourceRefreshListener.clone();
- for (Runnable listener : listeners) {
- try {
- getDisplay().syncExec(listener);
- } catch (Exception e) {
- log(e, "ResourceRefreshListener Failed"); //$NON-NLS-1$
- } finally {
- progress.worked(1);
- }
- }
- } catch (Throwable e) {
- EditorsPlugin.log(e, "Load Framework Resource Parser failed"); //$NON-NLS-1$
- EditorsPlugin.printToConsole("Framework Resource Parser",
- "Failed to parse");
- } finally {
- if (monitor != null) {
- monitor.done();
- }
- }
- return Status.OK_STATUS;
- }
- }.schedule();
- }
- }
-
- public void addResourceChangedListener(Runnable resourceRefreshListener) {
- mResourceRefreshListener.add(resourceRefreshListener);
- }
-
- public void removeResourceChangedListener(Runnable resourceRefreshListener) {
- mResourceRefreshListener.remove(resourceRefreshListener);
- }
-
- public static Display getDisplay() {
- IWorkbench bench = sPlugin.getWorkbench();
- if (bench != null) {
- return bench.getDisplay();
- }
- return null;
- }
-
- /**
- * Pings the usage start server.
- */
- private void pingUsageServer() {
- // In order to not block the plugin loading, so we spawn another thread.
- new Thread("Ping!") { //$NON-NLS-1$
- @Override
- public void run() {
- // get the version of the plugin
- String versionString = (String) getBundle().getHeaders().get(
- Constants.BUNDLE_VERSION);
- Version version = new Version(versionString);
-
- SdkStatsHelper.pingUsageServer("editors", version); //$NON-NLS-1$
- }
- }.start();
-
- }
-
- /**
- * Prints one or more message to the android console.
- * @param tag The tag to be associated with the message. Can be null.
- * @param objects the objects to print through their <code>toString</code> method.
- */
- public static synchronized void printToConsole(String tag, Object... objects) {
- StreamHelper.printToStream(sPlugin.mAndroidConsoleStream, tag, objects);
- }
-
- /**
- * Prints one or more error messages to the android console.
- * @param tag The tag to be associated with the message. Can be null.
- * @param objects the objects to print through their <code>toString</code> method.
- */
- public static synchronized void printErrorToConsole(String tag, Object... objects) {
- StreamHelper.printToStream(sPlugin.mAndroidConsoleErrorStream, tag, objects);
- }
-
- public static synchronized OutputStream getErrorStream() {
- return sPlugin.mAndroidConsoleErrorStream;
- }
-
- /**
- * Displays an error dialog box. This dialog box is ran asynchronously in the ui thread,
- * therefore this method can be called from any thread.
- * @param title The title of the dialog box
- * @param message The error message
- */
- public final static void displayError(final String title, final String message) {
- // get the current Display
- final Display display = getDisplay();
-
- // dialog box only run in ui thread..
- display.asyncExec(new Runnable() {
- public void run() {
- Shell shell = display.getActiveShell();
- MessageDialog.openError(shell, title, message);
- }
- });
- }
-
- /**
- * Display a yes/no question dialog box. This dialog is opened synchronously in the ui thread,
- * therefore this message can be called from any thread.
- * @param title The title of the dialog box
- * @param message The error message
- * @return true if OK was clicked.
- */
- public final static boolean displayPrompt(final String title, final String message) {
- // get the current Display and Shell
- final Display display = getDisplay();
-
- // we need to ask the user what he wants to do.
- final boolean[] wrapper = new boolean[] { false };
- display.syncExec(new Runnable() {
- public void run() {
- Shell shell = display.getActiveShell();
- wrapper[0] = MessageDialog.openQuestion(shell, title, message);
- }
- });
- return wrapper[0];
- }
-
- /**
- * Returns a {@link LayoutBridge} object possibly containing a {@link ILayoutBridge} object.
- * <p/>If {@link LayoutBridge#bridge} is <code>null</code>, {@link LayoutBridge#status} will
- * contain the reason (either {@link LoadStatus#LOADING} or {@link LoadStatus#FAILED}).
- * <p/>Valid {@link ILayoutBridge} objects are always initialized before being returned.
- */
- public synchronized LayoutBridge getLayoutBridge() {
- if (mLayoutBridgeInit == false && mLayoutBridge.bridge != null) {
- FrameworkResourceManager manager = FrameworkResourceManager.getInstance();
- mLayoutBridge.bridge.init(
- manager.getFrameworkFontLocation() + AndroidConstants.FD_DEFAULT_RES,
- manager.getEnumValueMap());
- mLayoutBridgeInit = true;
- }
- return mLayoutBridge;
- }
-
- /**
- * Loads the layout bridge from the dynamically loaded layoutlib.jar
- */
- private void loadLayoutBridge() {
- try {
- // reset to be sure we won't be using an obsolete version if we
- // get an exception somewhere.
- mLayoutBridge.bridge = null;
- mLayoutBridge.status = LayoutBridge.LoadStatus.LOADING;
-
- // get the URL for the file.
- File f = new File(
- FrameworkResourceManager.getInstance().getLayoutLibLocation());
- if (f.isFile() == false) {
- log(IStatus.ERROR, "layoutlib.jar is missing!"); //$NON-NLS-1$
- } else {
- URL url = f.toURL();
-
- // create a class loader. Because this jar reference interfaces
- // that are in the editors plugin, it's important to provide
- // a parent class loader.
- mBridgeClassLoader = new URLClassLoader(new URL[] { url },
- this.getClass().getClassLoader());
-
- // load the class
- Class<?> clazz = mBridgeClassLoader.loadClass(AndroidConstants.CLASS_BRIDGE);
- if (clazz != null) {
- // instantiate an object of the class.
- Constructor<?> constructor = clazz.getConstructor();
- if (constructor != null) {
- Object bridge = constructor.newInstance();
- if (bridge instanceof ILayoutBridge) {
- mLayoutBridge.bridge = (ILayoutBridge)bridge;
- }
- }
- }
-
- if (mLayoutBridge.bridge == null) {
- mLayoutBridge.status = LayoutBridge.LoadStatus.FAILED;
- log(IStatus.ERROR, "Failed to load " + AndroidConstants.CLASS_BRIDGE); //$NON-NLS-1$
- } else {
- mLayoutBridge.status = LayoutBridge.LoadStatus.LOADED;
- }
- }
- } catch (Throwable t) {
- mLayoutBridge.status = LayoutBridge.LoadStatus.FAILED;
- // log the error.
- log(t, "Failed to load the LayoutLib");
- }
- }
-
- public ClassLoader getLayoutlibBridgeClassLoader() {
- return mBridgeClassLoader;
- }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutTreePage.java b/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutTreePage.java
deleted file mode 100644
index c936be3..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutTreePage.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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.ide.eclipse.editors.layout;
-
-import com.android.ide.eclipse.editors.EditorsPlugin;
-import com.android.ide.eclipse.editors.resources.manager.ResourceFolder;
-import com.android.ide.eclipse.editors.resources.manager.ResourceManager;
-import com.android.ide.eclipse.editors.ui.tree.UiTreeBlock;
-import com.android.ide.eclipse.editors.uimodel.UiElementNode;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.ui.IEditorInput;
-import org.eclipse.ui.forms.IManagedForm;
-import org.eclipse.ui.forms.editor.FormPage;
-import org.eclipse.ui.forms.widgets.ScrolledForm;
-import org.eclipse.ui.part.FileEditorInput;
-
-/**
- * Page for the layout tree-based form editor.
- *
- * @deprecated This is being phased out. We use the GraphicalLayoutEditor instead.
- */
-public final class LayoutTreePage extends FormPage {
- /** Page id used for switching tabs programmatically */
- public final static String PAGE_ID = "layout_tree_page"; //$NON-NLS-1$
-
- /** Container editor */
- LayoutEditor mEditor;
-
- public LayoutTreePage(LayoutEditor editor) {
- super(editor, PAGE_ID, "Layout"); // tab's label, keep it short
- mEditor = editor;
- }
-
- /**
- * Creates the content in the form hosted in this page.
- *
- * @param managedForm the form hosted in this page.
- */
- @Override
- protected void createFormContent(IManagedForm managedForm) {
- super.createFormContent(managedForm);
- ScrolledForm form = managedForm.getForm();
-
- String configText = null;
- IEditorInput input = mEditor.getEditorInput();
- if (input instanceof FileEditorInput) {
- FileEditorInput fileInput = (FileEditorInput)input;
- IFile iFile = fileInput.getFile();
-
- ResourceFolder resFolder = ResourceManager.getInstance().getResourceFolder(iFile);
- if (resFolder != null) {
- configText = resFolder.getConfiguration().toDisplayString();
- }
- }
-
- if (configText != null) {
- form.setText(String.format("Android Layout (%1$s)", configText));
- } else {
- form.setText("Android Layout");
- }
-
- form.setImage(EditorsPlugin.getAndroidLogo());
-
- UiElementNode rootNode = mEditor.getUiRootNode();
- UiTreeBlock block = new UiTreeBlock(mEditor, rootNode,
- true /* autoCreateRoot */,
- null /* no element filters */,
- "Layout Elements",
- "List of all layout elements in this XML file.");
- block.createContent(managedForm);
- }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java b/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java
deleted file mode 100644
index 77b1df4..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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.ide.eclipse.editors.layout;
-
-import com.android.ide.eclipse.editors.EditorsPlugin;
-import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
-
-import org.eclipse.gef.palette.CombinedTemplateCreationEntry;
-import org.eclipse.gef.palette.MarqueeToolEntry;
-import org.eclipse.gef.palette.PaletteDrawer;
-import org.eclipse.gef.palette.PaletteGroup;
-import org.eclipse.gef.palette.PaletteRoot;
-import org.eclipse.gef.palette.PanningSelectionToolEntry;
-import org.eclipse.gef.requests.CreationFactory;
-
-import java.util.List;
-
-/**
- * Factory that creates the palette for the {@link GraphicalLayoutEditor}.
- */
-public class PaletteFactory {
-
- private static PaletteRoot sPaletteRoot;
- private static Runnable sSdkChangedListener;
-
- /** Static factory, nothing to instantiate here. */
- private PaletteFactory() {
- }
-
- public static PaletteRoot createPaletteRoot() {
- if (sSdkChangedListener == null) {
- sSdkChangedListener = new Runnable() {
- public void run() {
- if (sPaletteRoot != null) {
- // The SDK has changed. Remove the drawer groups and rebuild them.
- for (int n = sPaletteRoot.getChildren().size() - 1; n >= 0; n--) {
- sPaletteRoot.getChildren().remove(n);
- }
-
- addTools(sPaletteRoot);
- addViews(sPaletteRoot, "Layouts",
- LayoutDescriptors.getInstance().getLayoutDescriptors());
- addViews(sPaletteRoot, "Views",
- LayoutDescriptors.getInstance().getViewDescriptors());
- }
- }
- };
- EditorsPlugin.getDefault().addResourceChangedListener(sSdkChangedListener);
- }
-
- if (sPaletteRoot == null) {
- sPaletteRoot = new PaletteRoot();
- sSdkChangedListener.run();
- }
- return sPaletteRoot;
- }
-
- private static void addTools(PaletteRoot paletteRoot) {
- PaletteGroup group = new PaletteGroup("Tools");
-
- // Default tools: selection and marquee selection
- PanningSelectionToolEntry entry = new PanningSelectionToolEntry();
- group.add(entry);
- paletteRoot.setDefaultEntry(entry);
-
- group.add(new MarqueeToolEntry());
-
- paletteRoot.add(group);
- }
-
- private static void addViews(PaletteRoot paletteRoot, String groupName,
- List<ElementDescriptor> descriptors) {
- PaletteDrawer group = new PaletteDrawer(groupName);
-
- for (ElementDescriptor desc : descriptors) {
- CombinedTemplateCreationEntry entry = new CombinedTemplateCreationEntry(
- desc.getUiName(), // label
- desc.getTooltip(), // short description
- desc.getClass(), // template
- new ElementFactory(desc), // factory
- desc.getImageDescriptor(), // small icon
- desc.getImageDescriptor() // large icon
- );
- group.add(entry);
- }
-
- paletteRoot.add(group);
- }
-
- //------------------------------------------
-
- public static class ElementFactory implements CreationFactory {
-
- private final ElementDescriptor mDescriptor;
-
- public ElementFactory(ElementDescriptor descriptor) {
- mDescriptor = descriptor;
- }
-
- public Object getNewObject() {
- return mDescriptor;
- }
-
- public Object getObjectType() {
- return mDescriptor;
- }
-
- }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java b/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java
deleted file mode 100644
index 41d3747..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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.ide.eclipse.editors.layout;
-
-import com.android.ide.eclipse.editors.uimodel.UiElementNode;
-import com.android.layoutlib.api.IXmlPullParser;
-
-import org.w3c.dom.Node;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * XmlPullParser implementation on top of {@link UiElementNode}.
- * <p/>It's designed to work on layout files, and will most likely not work on other resource
- * files.
- */
-public final class UiElementPullParser implements IXmlPullParser {
-
- private final ArrayList<UiElementNode> mNodeStack = new ArrayList<UiElementNode>();
- private int mParsingState = START_DOCUMENT;
- private UiElementNode mRoot;
-
- public UiElementPullParser(UiElementNode top) {
- mRoot = top;
- push(mRoot);
- }
-
- private UiElementNode getCurrentNode() {
- if (mNodeStack.size() > 0) {
- return mNodeStack.get(mNodeStack.size()-1);
- }
-
- return null;
- }
-
- private Node getAttribute(int i) {
- if (mParsingState != START_TAG) {
- throw new IndexOutOfBoundsException();
- }
-
- // get the current uiNode
- UiElementNode uiNode = getCurrentNode();
-
- // get its xml node
- Node xmlNode = uiNode.getXmlNode();
-
- if (xmlNode != null) {
- return xmlNode.getAttributes().item(i);
- }
-
- return null;
- }
-
- private void push(UiElementNode node) {
- mNodeStack.add(node);
- }
-
- private UiElementNode pop() {
- return mNodeStack.remove(mNodeStack.size()-1);
- }
-
- // ------------- IXmlPullParser --------
-
- /**
- * {@inheritDoc}
- *
- * This implementation returns the underlying DOM node.
- */
- public Object getViewKey() {
- return getCurrentNode();
- }
-
- // ------------- XmlPullParser --------
-
- public void setFeature(String name, boolean state) throws XmlPullParserException {
- if (FEATURE_PROCESS_NAMESPACES.equals(name) && state) {
- return;
- }
- if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name) && state) {
- return;
- }
- throw new XmlPullParserException("Unsupported feature: " + name);
- }
-
- public boolean getFeature(String name) {
- if (FEATURE_PROCESS_NAMESPACES.equals(name)) {
- return true;
- }
- if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) {
- return true;
- }
- return false;
- }
-
- public void setProperty(String name, Object value) throws XmlPullParserException {
- throw new XmlPullParserException("setProperty() not supported");
- }
-
- public Object getProperty(String name) {
- return null;
- }
-
- public void setInput(Reader in) throws XmlPullParserException {
- throw new XmlPullParserException("setInput() not supported");
- }
-
- public void setInput(InputStream inputStream, String inputEncoding)
- throws XmlPullParserException {
- throw new XmlPullParserException("setInput() not supported");
- }
-
- public void defineEntityReplacementText(String entityName, String replacementText)
- throws XmlPullParserException {
- throw new XmlPullParserException("defineEntityReplacementText() not supported");
- }
-
- public String getNamespacePrefix(int pos) throws XmlPullParserException {
- throw new XmlPullParserException("getNamespacePrefix() not supported");
- }
-
- public String getInputEncoding() {
- return null;
- }
-
- public String getNamespace(String prefix) {
- throw new RuntimeException("getNamespace() not supported");
- }
-
- public int getNamespaceCount(int depth) throws XmlPullParserException {
- throw new XmlPullParserException("getNamespaceCount() not supported");
- }
-
- public String getPositionDescription() {
- return "XML DOM element depth:" + mNodeStack.size();
- }
-
- public String getNamespaceUri(int pos) throws XmlPullParserException {
- throw new XmlPullParserException("getNamespaceUri() not supported");
- }
-
- public int getColumnNumber() {
- return -1;
- }
-
- public int getLineNumber() {
- return -1;
- }
-
- public int getAttributeCount() {
- UiElementNode node = getCurrentNode();
- if (node != null) {
- return node.getUiAttributes().size();
- }
-
- return 0;
- }
-
- public String getAttributeName(int i) {
- Node attribute = getAttribute(i);
- if (attribute != null) {
- return attribute.getLocalName();
- }
-
- return null;
- }
-
- public String getAttributeNamespace(int i) {
- Node attribute = getAttribute(i);
- if (attribute != null) {
- return attribute.getNamespaceURI();
- }
- return ""; //$NON-NLS-1$
- }
-
- public String getAttributePrefix(int i) {
- Node attribute = getAttribute(i);
- if (attribute != null) {
- return attribute.getPrefix();
- }
- return null;
- }
-
- public String getAttributeType(int arg0) {
- return "CDATA";
- }
-
- public String getAttributeValue(int i) {
- Node attribute = getAttribute(i);
- if (attribute != null) {
- return attribute.getNodeValue();
- }
-
- return null;
- }
-
- public String getAttributeValue(String namespace, String localName) {
- // get the current uiNode
- UiElementNode uiNode = getCurrentNode();
-
- // get its xml node
- Node xmlNode = uiNode.getXmlNode();
-
- if (xmlNode != null) {
- Node attribute = xmlNode.getAttributes().getNamedItemNS(namespace, localName);
- if (attribute != null) {
- return attribute.getNodeValue();
- }
- }
-
- return null;
- }
-
- public int getDepth() {
- return mNodeStack.size();
- }
-
- public int getEventType() throws XmlPullParserException {
- return mParsingState;
- }
-
- public String getName() {
- if (mParsingState == START_TAG || mParsingState == END_TAG) {
- return getCurrentNode().getDescriptor().getXmlLocalName();
- }
-
- return null;
- }
-
- public String getNamespace() {
- if (mParsingState == START_TAG || mParsingState == END_TAG) {
- return getCurrentNode().getDescriptor().getNamespace();
- }
-
- return null;
- }
-
- public String getPrefix() {
- if (mParsingState == START_TAG || mParsingState == END_TAG) {
- // FIXME will NEVER work
- if (getCurrentNode().getDescriptor().getXmlLocalName().startsWith("android:")) { //$NON-NLS-1$
- return "android"; //$NON-NLS-1$
- }
- }
-
- return null;
- }
-
- public String getText() {
- return null;
- }
-
- public char[] getTextCharacters(int[] arg0) {
- return null;
- }
-
- public boolean isAttributeDefault(int arg0) {
- return false;
- }
-
- public boolean isEmptyElementTag() throws XmlPullParserException {
- if (mParsingState == START_TAG) {
- return getCurrentNode().getUiChildren().size() == 0;
- }
-
- throw new XmlPullParserException("Must be on START_TAG");
- }
-
- public boolean isWhitespace() throws XmlPullParserException {
- return false;
- }
-
- public int next() throws XmlPullParserException, IOException {
- UiElementNode node;
- switch (mParsingState) {
- case END_DOCUMENT:
- throw new XmlPullParserException("Nothing after the end");
- case START_DOCUMENT:
- /* intended fall-through */
- case START_TAG:
- // get the current node, and look for text or children (children first)
- node = getCurrentNode();
- List<UiElementNode> children = node.getUiChildren();
- if (children.size() > 0) {
- // move to the new child, and don't change the state.
- push(children.get(0));
-
- // in case the current state is CURRENT_DOC, we set the proper state.
- mParsingState = START_TAG;
- } else {
- if (mParsingState == START_DOCUMENT) {
- // this handles the case where there's no node.
- mParsingState = END_DOCUMENT;
- } else {
- mParsingState = END_TAG;
- }
- }
- break;
- case END_TAG:
- // look for a sibling. if no sibling, go back to the parent
- node = getCurrentNode();
- node = node.getUiNextSibling();
- if (node != null) {
- // to go to the sibling, we need to remove the current node,
- pop();
- // and add its sibling.
- push(node);
- mParsingState = START_TAG;
- } else {
- // move back to the parent
- pop();
-
- // we have only one element left (mRoot), then we're done with the document.
- if (mNodeStack.size() == 1) {
- mParsingState = END_DOCUMENT;
- } else {
- mParsingState = END_TAG;
- }
- }
- break;
- case TEXT:
- // not used
- break;
- case CDSECT:
- // not used
- break;
- case ENTITY_REF:
- // not used
- break;
- case IGNORABLE_WHITESPACE:
- // not used
- break;
- case PROCESSING_INSTRUCTION:
- // not used
- break;
- case COMMENT:
- // not used
- break;
- case DOCDECL:
- // not used
- break;
- }
-
- return mParsingState;
- }
-
- public int nextTag() throws XmlPullParserException, IOException {
- int eventType = next();
- if (eventType != START_TAG && eventType != END_TAG) {
- throw new XmlPullParserException("expected start or end tag", this, null);
- }
- return eventType;
- }
-
- public String nextText() throws XmlPullParserException, IOException {
- if (getEventType() != START_TAG) {
- throw new XmlPullParserException("parser must be on START_TAG to read next text", this,
- null);
- }
- int eventType = next();
- if (eventType == TEXT) {
- String result = getText();
- eventType = next();
- if (eventType != END_TAG) {
- throw new XmlPullParserException(
- "event TEXT it must be immediately followed by END_TAG", this, null);
- }
- return result;
- } else if (eventType == END_TAG) {
- return "";
- } else {
- throw new XmlPullParserException("parser must be on START_TAG or TEXT to read text",
- this, null);
- }
- }
-
- public int nextToken() throws XmlPullParserException, IOException {
- return next();
- }
-
- public void require(int type, String namespace, String name) throws XmlPullParserException,
- IOException {
- if (type != getEventType() || (namespace != null && !namespace.equals(getNamespace()))
- || (name != null && !name.equals(getName())))
- throw new XmlPullParserException("expected " + TYPES[type] + getPositionDescription());
- }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java
deleted file mode 100644
index 548a3a2..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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.ide.eclipse.editors.layout.parts;
-
-import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener;
-import com.android.ide.eclipse.editors.uimodel.UiElementNode;
-
-import org.eclipse.draw2d.geometry.Rectangle;
-import org.eclipse.gef.DragTracker;
-import org.eclipse.gef.EditPart;
-import org.eclipse.gef.EditPolicy;
-import org.eclipse.gef.GraphicalEditPart;
-import org.eclipse.gef.Request;
-import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
-import org.eclipse.gef.editpolicies.SelectionEditPolicy;
-import org.eclipse.gef.tools.SelectEditPartTracker;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-
-import java.util.List;
-
-/**
- * An {@link EditPart} for a {@link UiElementNode}.
- */
-public abstract class UiElementEditPart extends AbstractGraphicalEditPart
- implements IUiUpdateListener {
-
- public UiElementEditPart(UiElementNode uiElementNode) {
- setModel(uiElementNode);
- }
-
- //-------------------------
- // Derived classes must define these
-
- abstract protected void hideSelection();
- abstract protected void showSelection();
-
- //-------------------------
- // Base class overrides
-
- @Override
- public DragTracker getDragTracker(Request request) {
- return new SelectEditPartTracker(this);
- }
-
- @Override
- protected void createEditPolicies() {
- installEditPolicy(EditPolicy.SELECTION_FEEDBACK_ROLE, new SelectionEditPolicy() {
- @Override
- protected void hideSelection() {
- UiElementEditPart.this.hideSelection();
- }
-
- @Override
- protected void showSelection() {
- UiElementEditPart.this.showSelection();
- }
- });
- // TODO add editing policies
- }
-
- /* (non-javadoc)
- * Returns a List containing the children model objects.
- * Must not return null, instead use the super which returns an empty list.
- */
- @SuppressWarnings("unchecked")
- @Override
- protected List getModelChildren() {
- return getUiNode().getUiChildren();
- }
-
- @Override
- public void activate() {
- super.activate();
- getUiNode().addUpdateListener(this);
- }
-
- @Override
- public void deactivate() {
- super.deactivate();
- getUiNode().removeUpdateListener(this);
- }
-
- @Override
- protected void refreshVisuals() {
- if (getFigure().getParent() != null) {
- ((GraphicalEditPart) getParent()).setLayoutConstraint(this, getFigure(), getBounds());
- }
-
- // update the visuals of the children as well
- refreshChildrenVisuals();
- }
-
- protected void refreshChildrenVisuals() {
- if (children != null) {
- for (Object child : children) {
- if (child instanceof UiElementEditPart) {
- UiElementEditPart childPart = (UiElementEditPart)child;
- childPart.refreshVisuals();
- }
- }
- }
- }
-
- //-------------------------
- // IUiUpdateListener implementation
-
- public void uiElementNodeUpdated(UiElementNode ui_node, UiUpdateState state) {
- // TODO: optimize by refreshing only when needed
- switch(state) {
- case ATTR_UPDATED:
- refreshVisuals();
- break;
- case CHILDREN_CHANGED:
- refreshChildren();
-
- // new children list, need to update the layout
- refreshVisuals();
- break;
- case CREATED:
- refreshVisuals();
- break;
- case DELETED:
- // pass
- break;
- }
- }
-
- //-------------------------
- // Local methods
-
- /** @return The object model casted to an {@link UiElementNode} */
- protected final UiElementNode getUiNode() {
- return (UiElementNode) getModel();
- }
-
- protected final ElementDescriptor getDescriptor() {
- return getUiNode().getDescriptor();
- }
-
- protected final UiElementEditPart getEditPartParent() {
- EditPart parent = getParent();
- if (parent instanceof UiElementEditPart) {
- return (UiElementEditPart)parent;
- }
- return null;
- }
-
- /**
- * Returns a given XML attribute.
- * @param attrbName The local name of the attribute.
- * @return the attribute as a {@link String}, if it exists, or <code>null</code>
- */
- protected final String getStringAttr(String attrName) {
- UiElementNode uiNode = getUiNode();
- if (uiNode.getXmlNode() != null) {
- Node xmlNode = uiNode.getXmlNode();
- if (xmlNode != null) {
- NamedNodeMap nodeAttributes = xmlNode.getAttributes();
- if (nodeAttributes != null) {
- Node attr = nodeAttributes.getNamedItemNS(
- AndroidConstants.NS_RESOURCES, attrName);
- if (attr != null) {
- return attr.getNodeValue();
- }
- }
- }
- }
- return null;
- }
-
- protected final Rectangle getBounds() {
- UiElementNode model = (UiElementNode)getModel();
-
- Object editData = model.getEditData();
- if (editData instanceof Rectangle) {
- return (Rectangle)editData; // return a copy?
- }
-
- // return a dummy rect
- return new Rectangle(0, 0, 0, 0);
- }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutEditPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutEditPart.java
deleted file mode 100644
index d9433ca..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutEditPart.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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.ide.eclipse.editors.layout.parts;
-
-import com.android.ide.eclipse.editors.uimodel.UiElementNode;
-
-import org.eclipse.draw2d.ColorConstants;
-import org.eclipse.draw2d.IFigure;
-import org.eclipse.draw2d.Label;
-import org.eclipse.draw2d.LineBorder;
-import org.eclipse.draw2d.XYLayout;
-import org.eclipse.gef.EditPolicy;
-import org.eclipse.gef.commands.Command;
-import org.eclipse.gef.editpolicies.ContainerEditPolicy;
-import org.eclipse.gef.requests.CreateRequest;
-
-/**
- * Graphical edit part for an {@link UiElementNode} that represents a ViewLayout.
- * <p/>
- * It acts as a simple container.
- */
-public final class UiLayoutEditPart extends UiElementEditPart {
-
- public UiLayoutEditPart(UiElementNode uiElementNode) {
- super(uiElementNode);
- }
-
- @Override
- protected void createEditPolicies() {
- super.createEditPolicies();
-
- installEditPolicy(EditPolicy.CONTAINER_ROLE, new ContainerEditPolicy() {
- @Override
- protected Command getCreateCommand(CreateRequest request) {
- return null;
- }
- });
- }
-
- @Override
- protected IFigure createFigure() {
- Label f = new Label();
- f.setLayoutManager(new XYLayout());
- return f;
- }
-
- @Override
- protected void hideSelection() {
- IFigure f = getFigure();
- if (f instanceof Label) {
- f.setBorder(null);
- }
- }
-
- @Override
- protected void showSelection() {
- IFigure f = getFigure();
- if (f instanceof Label) {
- f.setBorder(new LineBorder(ColorConstants.red, 1));
- }
- }
-
- public void showDropTarget() {
- IFigure f = getFigure();
- if (f instanceof Label) {
- f.setBorder(new LineBorder(ColorConstants.blue, 1));
- }
- }
-
- public void hideDropTarget() {
- hideSelection();
- }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java b/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java
deleted file mode 100644
index 7e38032..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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.ide.eclipse.editors.ui.tree;
-
-import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
-import com.android.ide.eclipse.editors.uimodel.UiElementNode;
-
-import org.apache.xml.serialize.Method;
-import org.apache.xml.serialize.OutputFormat;
-import org.apache.xml.serialize.XMLSerializer;
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.swt.dnd.Clipboard;
-import org.eclipse.swt.dnd.TextTransfer;
-import org.eclipse.swt.dnd.Transfer;
-import org.eclipse.ui.ISharedImages;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
-import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
-import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
-import org.eclipse.wst.xml.core.internal.document.NodeContainer;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-import java.io.StringWriter;
-
-
-/**
- * Provides Cut and Copy actions for the tree nodes.
- */
-public class CopyCutAction extends Action {
- private UiElementNode mUiNode;
- private boolean mPerformCut;
- private final AndroidEditor mEditor;
- private final Clipboard mClipboard;
- private final ICommitXml mXmlCommit;
-
- /**
- * Creates a new Copy or Cut action.
- *
- * @param ui_node The UI node to cut or copy. It *must* have a non-null XML node.
- * @param perform_cut True if the operation is cut, false if it is copy.
- */
- public CopyCutAction(AndroidEditor editor, Clipboard clipboard, ICommitXml xmlCommit,
- UiElementNode ui_node, boolean perform_cut) {
- super(perform_cut ? "Cut" : "Copy");
- mEditor = editor;
- mClipboard = clipboard;
- mXmlCommit = xmlCommit;
-
- ISharedImages images = PlatformUI.getWorkbench().getSharedImages();
- if (perform_cut) {
- setImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT));
- setHoverImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT));
- setDisabledImageDescriptor(
- images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT_DISABLED));
- } else {
- setImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
- setHoverImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
- setDisabledImageDescriptor(
- images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY_DISABLED));
- }
-
- mUiNode = ui_node;
- mPerformCut = perform_cut;
- }
-
- /**
- * Performs the cut or copy action.
- * First an XML serializer is used to turn the existing XML node into a valid
- * XML fragment, which is added as text to the clipboard.
- */
- @Override
- public void run() {
- super.run();
- try {
- String data = null;
-
- // Get the data directly from the editor.
-
- // Commit the current pages first, to make sure the XML is in sync.
- if (mXmlCommit != null) {
- mXmlCommit.commitPendingXmlChanges();
- }
-
- // Committing may change the XML structure.
- Node xml_node = mUiNode.getXmlNode();
- if (xml_node == null) {
- return;
- }
-
- IStructuredModel model = mEditor.getModelForRead();
- try {
- IStructuredDocument sse_doc = mEditor.getStructuredDocument();
- if (xml_node instanceof NodeContainer) {
- // The easy way to get the source of an SSE XML node.
- data = ((NodeContainer) xml_node).getSource();
- } else if (xml_node instanceof IndexedRegion && sse_doc != null) {
- // Try harder.
- IndexedRegion region = (IndexedRegion) xml_node;
- int start = region.getStartOffset();
- int end = region.getEndOffset();
-
- if (end > start) {
- data = sse_doc.get(start, end - start);
- }
- }
- } catch (BadLocationException e) {
- // the region offset was invalid. ignore.
- } finally {
- model.releaseFromRead();
- }
-
- // In the unlikely event that IStructuredDocument failed to extract the text
- // directly from the editor, try to fall back on a direct XML serialization
- // of the XML node. This uses the generic Node interface with no SSE tricks.
- if (data == null) {
- StringWriter sw = new StringWriter();
- XMLSerializer serializer = new XMLSerializer(sw,
- new OutputFormat(Method.XML,
- OutputFormat.Defaults.Encoding /* utf-8 */,
- true /* indent */));
- // Serialize will throw an IOException if it fails.
- serializer.serialize((Element) xml_node);
- data = sw.toString();
- }
-
- if (data != null && data.length() > 0) {
- mClipboard.setContents(
- new Object[] { data },
- new Transfer[] { TextTransfer.getInstance() });
- if (mPerformCut) {
- mUiNode.deleteXmlNode();
- }
- }
- } catch (Exception e) {
- EditorsPlugin.log(e, "CopyCutAction failed for UI node %1$s", //$NON-NLS-1$
- mUiNode.getBreadcrumbTrailDescription(true));
- }
- }
-}
-
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java b/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java
deleted file mode 100644
index b3d0755..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * 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.ide.eclipse.editors.ui.tree;
-
-import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
-import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
-import com.android.ide.eclipse.editors.uimodel.UiElementNode;
-
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.viewers.ILabelProvider;
-import org.eclipse.swt.widgets.Shell;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-
-/**
- * Performs basic actions on an XML tree: add node, remove node, move up/down.
- */
-public abstract class UiActions implements ICommitXml {
-
- public UiActions() {
- }
-
- //---------------------
- // Actual implementations must override these to provide specific hooks
-
- /** Returns the UiDocumentNode for the current model. */
- abstract protected UiElementNode getRootNode();
-
- /** Commits pending data before the XML model is modified. */
- abstract public void commitPendingXmlChanges();
-
- /**
- * Utility method to select an outline item based on its model node
- *
- * @param ui_node The node to select. Can be null (in which case nothing should happen)
- */
- abstract protected void selectUiNode(UiElementNode ui_node);
-
- //---------------------
-
- /**
- * Called when the "Add..." button next to the tree view is selected.
- * <p/>
- * This simplified version of doAdd does not support descriptor filters and creates
- * a new {@link UiModelTreeLabelProvider} for each call.
- */
- public void doAdd(UiElementNode ui_node, Shell shell) {
- doAdd(ui_node, null /* descriptorFilters */, shell, new UiModelTreeLabelProvider());
- }
-
- /**
- * Called when the "Add..." button next to the tree view is selected.
- *
- * Displays a selection dialog that lets the user select which kind of node
- * to create, depending on the current selection.
- */
- public void doAdd(UiElementNode ui_node,
- ElementDescriptor[] descriptorFilters,
- Shell shell, ILabelProvider labelProvider) {
- // If the root node is a document with already a root, use it as the root node
- UiElementNode root_node = getRootNode();
- if (root_node instanceof UiDocumentNode &&
- root_node.getUiChildren().size() > 0) {
- root_node = root_node.getUiChildren().get(0);
- }
-
- NewItemSelectionDialog dlg = new NewItemSelectionDialog(
- shell,
- labelProvider,
- descriptorFilters,
- ui_node, root_node);
- dlg.open();
- Object[] results = dlg.getResult();
- if (results != null && results.length > 0) {
- UiElementNode ui_new = addNewTreeElement(dlg.getChosenRootNode(),
- (ElementDescriptor) results[0]);
-
- selectUiNode(ui_new);
- }
- }
-
- /**
- * Called when the "Remove" button is selected.
- *
- * If the tree has a selection, remove it.
- * This simply deletes the XML node attached to the UI node: when the XML model fires the
- * update event, the tree will get refreshed.
- */
- public void doRemove(final UiElementNode ui_node, Shell shell) {
- if (MessageDialog.openQuestion(shell,
- "Remove element from Android XML", // title
- String.format("Do you really want to remove %1$s?",
- ui_node.getBreadcrumbTrailDescription(false /* include_root */)))) {
- commitPendingXmlChanges();
- getRootNode().getEditor().editXmlModel(new Runnable() {
- public void run() {
- UiElementNode previous = ui_node.getUiPreviousSibling();
- UiElementNode parent = ui_node.getUiParent();
-
- // delete node
- ui_node.deleteXmlNode();
-
- // try to select the previous sibling or the parent
- if (previous != null) {
- selectUiNode(previous);
- } else if (parent != null) {
- selectUiNode(parent);
- }
- }
- });
- }
- }
-
- /**
- * Called when the "Up" button is selected.
- * <p/>
- * If the tree has a selection, move it up, either in the child list or as the last child
- * of the previous parent.
- */
- public void doUp(final UiElementNode ui_node) {
- final Node[] select_xml_node = { null };
- // the node will move either up to its parent or grand-parent
- UiElementNode search_root = ui_node.getUiParent();
- if (search_root != null && search_root.getUiParent() != null) {
- search_root = search_root.getUiParent();
- }
-
- commitPendingXmlChanges();
- getRootNode().getEditor().editXmlModel(new Runnable() {
- public void run() {
- Node xml_node = ui_node.getXmlNode();
- if (xml_node != null) {
- Node xml_parent = xml_node.getParentNode();
- if (xml_parent != null) {
- UiElementNode ui_prev = ui_node.getUiPreviousSibling();
- if (ui_prev != null && ui_prev.getXmlNode() != null) {
- // This node is not the first one of the parent, so it can be
- // removed and then inserted before its previous sibling.
- // If the previous sibling can have children, though, then it
- // is inserted at the end of the children list.
- Node xml_prev = ui_prev.getXmlNode();
- if (ui_prev.getDescriptor().hasChildren()) {
- xml_prev.appendChild(xml_parent.removeChild(xml_node));
- select_xml_node[0] = xml_node;
- } else {
- xml_parent.insertBefore(
- xml_parent.removeChild(xml_node),
- xml_prev);
- select_xml_node[0] = xml_node;
- }
- } else if (!(xml_parent instanceof Document) &&
- xml_parent.getParentNode() != null &&
- !(xml_parent.getParentNode() instanceof Document)) {
- // If the node is the first one of the child list of its
- // parent, move it up in the hierarchy as previous sibling
- // to the parent. This is only possible if the parent of the
- // parent is not a document.
- Node grand_parent = xml_parent.getParentNode();
- grand_parent.insertBefore(xml_parent.removeChild(xml_node),
- xml_parent);
- select_xml_node[0] = xml_node;
- }
- }
- }
- }
- });
-
- if (select_xml_node[0] == null) {
- // The XML node has not been moved, we can just select the same UI node
- selectUiNode(ui_node);
- } else {
- // The XML node has moved. At this point the UI model has been reloaded
- // and the XML node has been affected to a new UI node. Find that new UI
- // node and select it.
- if (search_root == null) {
- search_root = ui_node.getUiRoot();
- }
- if (search_root != null) {
- selectUiNode(search_root.findXmlNode(select_xml_node[0]));
- }
- }
- }
-
- /**
- * Called when the "Down" button is selected.
- *
- * If the tree has a selection, move it down, either in the same child list or as the
- * first child of the next parent.
- */
- public void doDown(final UiElementNode ui_node) {
- final Node[] select_xml_node = { null };
- // the node will move either down to its parent or grand-parent
- UiElementNode search_root = ui_node.getUiParent();
- if (search_root != null && search_root.getUiParent() != null) {
- search_root = search_root.getUiParent();
- }
-
- commitPendingXmlChanges();
- getRootNode().getEditor().editXmlModel(new Runnable() {
- public void run() {
- Node xml_node = ui_node.getXmlNode();
- if (xml_node != null) {
- Node xml_parent = xml_node.getParentNode();
- if (xml_parent != null) {
- UiElementNode ui_next = ui_node.getUiNextSibling();
- if (ui_next != null && ui_next.getXmlNode() != null) {
- // This node is not the last one of the parent, so it can be
- // removed and then inserted after its next sibling.
- // If the next sibling is a node that can have children, though,
- // then the node is inserted as the first child.
- Node xml_next = ui_next.getXmlNode();
- if (ui_next.getDescriptor().hasChildren()) {
- // Note: insertBefore works as append if the ref node is
- // null, i.e. when the node doesn't have children yet.
- xml_next.insertBefore(xml_parent.removeChild(xml_node),
- xml_next.getFirstChild());
- select_xml_node[0] = xml_node;
- } else {
- // Insert "before after next" ;-)
- xml_parent.insertBefore(xml_parent.removeChild(xml_node),
- xml_next.getNextSibling());
- select_xml_node[0] = xml_node;
- }
- } else if (!(xml_parent instanceof Document) &&
- xml_parent.getParentNode() != null &&
- !(xml_parent.getParentNode() instanceof Document)) {
- // This node is the last node of its parent.
- // If neither the parent nor the grandparent is a document,
- // then the node can be insert right after the parent.
- Node grand_parent = xml_parent.getParentNode();
- grand_parent.insertBefore(xml_parent.removeChild(xml_node),
- xml_parent.getNextSibling());
- select_xml_node[0] = xml_node;
- }
- }
- }
- }
- });
-
- if (select_xml_node[0] == null) {
- // The XML node has not been moved, we can just select the same UI node
- selectUiNode(ui_node);
- } else {
- // The XML node has moved. At this point the UI model has been reloaded
- // and the XML node has been affected to a new UI node. Find that new UI
- // node and select it.
- if (search_root == null) {
- search_root = ui_node.getUiRoot();
- }
- if (search_root != null) {
- selectUiNode(search_root.findXmlNode(select_xml_node[0]));
- }
- }
- }
-
- //---------------------
-
- /**
- * Adds a new element of the given descriptor's type to the given UI parent node.
- *
- * This actually creates the corresponding XML node in the XML model, which in turn
- * will refresh the current tree view.
- *
- * @param ui_parent An existing UI node or null to add to the tree root
- * @param elementDescriptor The descriptor of the element to add
- * @return The {@link UiElementNode} that has been added to the UI tree.
- */
- private UiElementNode addNewTreeElement(UiElementNode ui_parent,
- ElementDescriptor elementDescriptor) {
- commitPendingXmlChanges();
- final UiElementNode ui_new = ui_parent.appendNewUiChild(elementDescriptor);
- UiElementNode root_node = getRootNode();
-
- root_node.getEditor().editXmlModel(new Runnable() {
- public void run() {
- DescriptorsUtils.setDefaultLayoutAttributes(ui_new);
- ui_new.createXmlNode();
- }
- });
- return ui_new;
- }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/.project b/tools/eclipse/plugins/com.android.ide.eclipse.platform/.project
deleted file mode 100644
index 145d97c..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/.project
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>platform</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.ManifestBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.SchemaBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.pde.PluginNature</nature>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
-</projectDescription>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/META-INF/MANIFEST.MF b/tools/eclipse/plugins/com.android.ide.eclipse.platform/META-INF/MANIFEST.MF
deleted file mode 100644
index 178275a..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,15 +0,0 @@
-Manifest-Version: 1.0
-Bundle-ManifestVersion: 2
-Bundle-Name: Android Platform Development Toolkit
-Bundle-SymbolicName: com.android.ide.eclipse.platform;singleton:=true
-Bundle-Version: 0.8.1.qualifier
-Bundle-ClassPath: .
-Bundle-Activator: com.android.ide.eclipse.platform.AndroidPlatformPlugin
-Bundle-Vendor: The Android Open Source Project
-Require-Bundle: org.eclipse.ui,
- org.eclipse.core.runtime,
- com.android.ide.eclipse.ddms,
- com.android.ide.eclipse.common,
- org.eclipse.core.resources,
- org.eclipse.jdt.core
-Eclipse-LazyStart: true
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/MODULE_LICENSE_EPL b/tools/eclipse/plugins/com.android.ide.eclipse.platform/MODULE_LICENSE_EPL
deleted file mode 100644
index e69de29..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/MODULE_LICENSE_EPL
+++ /dev/null
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/NOTICE b/tools/eclipse/plugins/com.android.ide.eclipse.platform/NOTICE
deleted file mode 100644
index 49c101d..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/NOTICE
+++ /dev/null
@@ -1,224 +0,0 @@
-*Eclipse Public License - v 1.0*
-
-THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
-PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF
-THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
-
-*1. DEFINITIONS*
-
-"Contribution" means:
-
-a) in the case of the initial Contributor, the initial code and
-documentation distributed under this Agreement, and
-b) in the case of each subsequent Contributor:
-
-i) changes to the Program, and
-
-ii) additions to the Program;
-
-where such changes and/or additions to the Program originate from and
-are distributed by that particular Contributor. A Contribution
-'originates' from a Contributor if it was added to the Program by such
-Contributor itself or anyone acting on such Contributor's behalf.
-Contributions do not include additions to the Program which: (i) are
-separate modules of software distributed in conjunction with the Program
-under their own license agreement, and (ii) are not derivative works of
-the Program.
-
-"Contributor" means any person or entity that distributes the Program.
-
-"Licensed Patents " mean patent claims licensable by a Contributor which
-are necessarily infringed by the use or sale of its Contribution alone
-or when combined with the Program.
-
-"Program" means the Contributions distributed in accordance with this
-Agreement.
-
-"Recipient" means anyone who receives the Program under this Agreement,
-including all Contributors.
-
-*2. GRANT OF RIGHTS*
-
-a) Subject to the terms of this Agreement, each Contributor hereby
-grants Recipient a non-exclusive, worldwide, royalty-free copyright
-license to reproduce, prepare derivative works of, publicly display,
-publicly perform, distribute and sublicense the Contribution of such
-Contributor, if any, and such derivative works, in source code and
-object code form.
-
-b) Subject to the terms of this Agreement, each Contributor hereby
-grants Recipient a non-exclusive, worldwide, royalty-free patent license
-under Licensed Patents to make, use, sell, offer to sell, import and
-otherwise transfer the Contribution of such Contributor, if any, in
-source code and object code form. This patent license shall apply to the
-combination of the Contribution and the Program if, at the time the
-Contribution is added by the Contributor, such addition of the
-Contribution causes such combination to be covered by the Licensed
-Patents. The patent license shall not apply to any other combinations
-which include the Contribution. No hardware per se is licensed hereunder.
-
-c) Recipient understands that although each Contributor grants the
-licenses to its Contributions set forth herein, no assurances are
-provided by any Contributor that the Program does not infringe the
-patent or other intellectual property rights of any other entity. Each
-Contributor disclaims any liability to Recipient for claims brought by
-any other entity based on infringement of intellectual property rights
-or otherwise. As a condition to exercising the rights and licenses
-granted hereunder, each Recipient hereby assumes sole responsibility to
-secure any other intellectual property rights needed, if any. For
-example, if a third party patent license is required to allow Recipient
-to distribute the Program, it is Recipient's responsibility to acquire
-that license before distributing the Program.
-
-d) Each Contributor represents that to its knowledge it has sufficient
-copyright rights in its Contribution, if any, to grant the copyright
-license set forth in this Agreement.
-
-*3. REQUIREMENTS*
-
-A Contributor may choose to distribute the Program in object code form
-under its own license agreement, provided that:
-
-a) it complies with the terms and conditions of this Agreement; and
-
-b) its license agreement:
-
-i) effectively disclaims on behalf of all Contributors all warranties
-and conditions, express and implied, including warranties or conditions
-of title and non-infringement, and implied warranties or conditions of
-merchantability and fitness for a particular purpose;
-
-ii) effectively excludes on behalf of all Contributors all liability for
-damages, including direct, indirect, special, incidental and
-consequential damages, such as lost profits;
-
-iii) states that any provisions which differ from this Agreement are
-offered by that Contributor alone and not by any other party; and
-
-iv) states that source code for the Program is available from such
-Contributor, and informs licensees how to obtain it in a reasonable
-manner on or through a medium customarily used for software exchange.
-
-When the Program is made available in source code form:
-
-a) it must be made available under this Agreement; and
-
-b) a copy of this Agreement must be included with each copy of the Program.
-
-Contributors may not remove or alter any copyright notices contained
-within the Program.
-
-Each Contributor must identify itself as the originator of its
-Contribution, if any, in a manner that reasonably allows subsequent
-Recipients to identify the originator of the Contribution.
-
-*4. COMMERCIAL DISTRIBUTION*
-
-Commercial distributors of software may accept certain responsibilities
-with respect to end users, business partners and the like. While this
-license is intended to facilitate the commercial use of the Program, the
-Contributor who includes the Program in a commercial product offering
-should do so in a manner which does not create potential liability for
-other Contributors. Therefore, if a Contributor includes the Program in
-a commercial product offering, such Contributor ("Commercial
-Contributor") hereby agrees to defend and indemnify every other
-Contributor ("Indemnified Contributor") against any losses, damages and
-costs (collectively "Losses") arising from claims, lawsuits and other
-legal actions brought by a third party against the Indemnified
-Contributor to the extent caused by the acts or omissions of such
-Commercial Contributor in connection with its distribution of the
-Program in a commercial product offering. The obligations in this
-section do not apply to any claims or Losses relating to any actual or
-alleged intellectual property infringement. In order to qualify, an
-Indemnified Contributor must: a) promptly notify the Commercial
-Contributor in writing of such claim, and b) allow the Commercial
-Contributor to control, and cooperate with the Commercial Contributor
-in, the defense and any related settlement negotiations. The Indemnified
-Contributor may participate in any such claim at its own expense.
-
-For example, a Contributor might include the Program in a commercial
-product offering, Product X. That Contributor is then a Commercial
-Contributor. If that Commercial Contributor then makes performance
-claims, or offers warranties related to Product X, those performance
-claims and warranties are such Commercial Contributor's responsibility
-alone. Under this section, the Commercial Contributor would have to
-defend claims against the other Contributors related to those
-performance claims and warranties, and if a court requires any other
-Contributor to pay any damages as a result, the Commercial Contributor
-must pay those damages.
-
-*5. NO WARRANTY*
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED
-ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
-EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES
-OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR
-A PARTICULAR PURPOSE. Each Recipient is solely responsible for
-determining the appropriateness of using and distributing the Program
-and assumes all risks associated with its exercise of rights under this
-Agreement , including but not limited to the risks and costs of program
-errors, compliance with applicable laws, damage to or loss of data,
-programs or equipment, and unavailability or interruption of operations.
-
-*6. DISCLAIMER OF LIABILITY*
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
-ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
-WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
-DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
-HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-*7. GENERAL*
-
-If any provision of this Agreement is invalid or unenforceable under
-applicable law, it shall not affect the validity or enforceability of
-the remainder of the terms of this Agreement, and without further action
-by the parties hereto, such provision shall be reformed to the minimum
-extent necessary to make such provision valid and enforceable.
-
-If Recipient institutes patent litigation against any entity (including
-a cross-claim or counterclaim in a lawsuit) alleging that the Program
-itself (excluding combinations of the Program with other software or
-hardware) infringes such Recipient's patent(s), then such Recipient's
-rights granted under Section 2(b) shall terminate as of the date such
-litigation is filed.
-
-All Recipient's rights under this Agreement shall terminate if it fails
-to comply with any of the material terms or conditions of this Agreement
-and does not cure such failure in a reasonable period of time after
-becoming aware of such noncompliance. If all Recipient's rights under
-this Agreement terminate, Recipient agrees to cease use and distribution
-of the Program as soon as reasonably practicable. However, Recipient's
-obligations under this Agreement and any licenses granted by Recipient
-relating to the Program shall continue and survive.
-
-Everyone is permitted to copy and distribute copies of this Agreement,
-but in order to avoid inconsistency the Agreement is copyrighted and may
-only be modified in the following manner. The Agreement Steward reserves
-the right to publish new versions (including revisions) of this
-Agreement from time to time. No one other than the Agreement Steward has
-the right to modify this Agreement. The Eclipse Foundation is the
-initial Agreement Steward. The Eclipse Foundation may assign the
-responsibility to serve as the Agreement Steward to a suitable separate
-entity. Each new version of the Agreement will be given a distinguishing
-version number. The Program (including Contributions) may always be
-distributed subject to the version of the Agreement under which it was
-received. In addition, after a new version of the Agreement is
-published, Contributor may elect to distribute the Program (including
-its Contributions) under the new version. Except as expressly stated in
-Sections 2(a) and 2(b) above, Recipient receives no rights or licenses
-to the intellectual property of any Contributor under this Agreement,
-whether expressly, by implication, estoppel or otherwise. All rights in
-the Program not expressly granted under this Agreement are reserved.
-
-This Agreement is governed by the laws of the State of New York and the
-intellectual property laws of the United States of America. No party to
-this Agreement will bring a legal action under this Agreement more than
-one year after the cause of action arose. Each party waives its rights
-to a jury trial in any resulting litigation.
-
-
-
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/build.properties b/tools/eclipse/plugins/com.android.ide.eclipse.platform/build.properties
deleted file mode 100644
index 6c480f3..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/build.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-source.. = src/
-output.. = bin/
-bin.includes = META-INF/,\
- .,\
- plugin.xml,\
- icons/
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/icons/android_project.png b/tools/eclipse/plugins/com.android.ide.eclipse.platform/icons/android_project.png
deleted file mode 100644
index 6171025..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/icons/android_project.png
+++ /dev/null
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/plugin.xml b/tools/eclipse/plugins/com.android.ide.eclipse.platform/plugin.xml
deleted file mode 100644
index 1c5d067..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/plugin.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?eclipse version="3.2"?>
-<plugin>
- <extension
- id="PlatformNature"
- name="PlatformNature"
- point="org.eclipse.core.resources.natures">
- <runtime>
- <run class="com.android.ide.eclipse.platform.project.PlatformNature"/>
- </runtime>
- </extension>
- <extension
- point="org.eclipse.ui.ide.projectNatureImages">
- <image
- icon="icons/android_project.png"
- id="com.android.ide.eclipse.platform.PlatformNature.image"
- natureId="com.android.ide.eclipse.platform.PlatformNature">
- </image>
- </extension>
- <extension
- point="org.eclipse.ui.preferencePages">
- <page
- class="com.android.ide.eclipse.platform.preferences.AndroidPreferencePage"
- id="com.android.ide.eclipse.preferences.main"
- name="Android"/>
- </extension>
- <extension
- point="org.eclipse.jdt.core.classpathContainerInitializer">
- <classpathContainerInitializer
- class="com.android.ide.eclipse.platform.project.PlatformClasspathContainerInitializer"
- id="com.android.ide.eclipse.platform.DUMMY_CONTAINER">
- </classpathContainerInitializer>
- </extension>
- <extension
- point="org.eclipse.ui.popupMenus">
- <objectContribution
- id="com.android.ide.eclipse.platform.contribution1"
- nameFilter="*"
- objectClass="org.eclipse.core.resources.IProject"
- adaptable="true">
- <menu
- id="com.android.ide.eclipse.platform.AndroidTools"
- label="Android Tools"
- path="additions">
- <separator name="group1"/>
- </menu>
- <visibility>
- <not>
- <or>
- <objectState
- name="projectNature"
- value="com.android.ide.eclipse.platform.PlatformNature"/>
- <objectState
- name="open"
- value="false"/>
- </or>
- </not>
- </visibility>
- <action
- class="com.android.ide.eclipse.platform.project.ConvertToPlatformAction"
- enablesFor="1"
- id="com.android.ide.eclipse.platform.ConvertToPlatformAction"
- label="Convert To Android Project"
- menubarPath="com.android.ide.eclipse.platform.AndroidTools/group1"/>
- </objectContribution>
- </extension>
-</plugin>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/AndroidPlatformPlugin.java b/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/AndroidPlatformPlugin.java
deleted file mode 100644
index 5fa8a29..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/AndroidPlatformPlugin.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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.ide.eclipse.platform;
-
-import com.android.ddmuilib.StackTracePanel;
-import com.android.ddmuilib.StackTracePanel.ISourceRevealer;
-import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.project.BaseProjectHelper;
-import com.android.ide.eclipse.ddms.DdmsPlugin;
-import com.android.ide.eclipse.platform.project.PlatformNature;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IWorkspace;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.Preferences;
-import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
-import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.preference.IPreferenceStore;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.plugin.AbstractUIPlugin;
-import org.osgi.framework.BundleContext;
-
-import java.io.File;
-
-/**
- * The activator class controls the plug-in life cycle
- */
-public class AndroidPlatformPlugin extends AbstractUIPlugin {
-
- // The plug-in ID
- public static final String PLUGIN_ID = "com.android.ide.eclipse.apdt"; //$NON-NLS-1$
-
- public final static String PREFS_DEVICE_DIRECTORY = PLUGIN_ID + ".deviceDir"; //$NON-NLS-1$
-
- // The shared instance
- private static AndroidPlatformPlugin sPlugin;
-
- private IPreferenceStore mStore;
- private String mOsDeviceDirectory;
-
- /**
- * The constructor
- */
- public AndroidPlatformPlugin() {
- sPlugin = this;
- }
-
- /*
- * (non-Javadoc)
- * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
- */
- @Override
- public void start(BundleContext context) throws Exception {
- super.start(context);
-
- // get the eclipse store
- mStore = getPreferenceStore();
-
- // set the listener for the preference change
- Preferences prefs = getPluginPreferences();
- prefs.addPropertyChangeListener(new IPropertyChangeListener() {
- public void propertyChange(PropertyChangeEvent event) {
- // get the name of the property that changed.
- String property = event.getProperty();
-
- // if the SDK changed, we update the cached version
- if (PREFS_DEVICE_DIRECTORY.equals(property)) {
- // get the new one from the preferences
- mOsDeviceDirectory = (String)event.getNewValue();
-
- // make sure it does not ends with a separator
- if (mOsDeviceDirectory.endsWith(File.separator)) {
- mOsDeviceDirectory = mOsDeviceDirectory.substring(0,
- mOsDeviceDirectory.length() - 1);
- }
-
- // finally restart adb, in case it's a different version
- String adbLocation = getOsAdbLocation();
- if (adbLocation != null) {
- DdmsPlugin.setAdb(adbLocation, true /* startAdb */);
- }
- }
- }
- });
-
-
- mOsDeviceDirectory = mStore.getString(PREFS_DEVICE_DIRECTORY);
-
- if (mOsDeviceDirectory.length() == 0) {
- // get the current Display
- final Display display = sPlugin.getWorkbench().getDisplay();
-
- // dialog box only run in ui thread..
- display.asyncExec(new Runnable() {
- public void run() {
- Shell shell = display.getActiveShell();
- MessageDialog.openError(shell, "Android Preferences",
- "Location of the device directory is missing.");
- }
- });
- } else {
- // give the location of adb to ddms
- String adbLocation = getOsAdbLocation();
- if (adbLocation != null) {
- DdmsPlugin.setAdb(adbLocation, true);
- }
- }
-
- // and give it the debug launcher for android projects
- DdmsPlugin.setRunningAppDebugLauncher(new DdmsPlugin.IDebugLauncher() {
- public boolean debug(String packageName, int port) {
- return false;
- }
- });
-
- StackTracePanel.setSourceRevealer(new ISourceRevealer() {
- public void reveal(String applicationName, String className, int line) {
- IProject project = getDeviceProject();
- if (project != null) {
- BaseProjectHelper.revealSource(project, className, line);
- }
- }
- });
-
- }
-
- /*
- * (non-Javadoc)
- * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
- */
- @Override
- public void stop(BundleContext context) throws Exception {
- sPlugin = null;
- super.stop(context);
- }
-
- /**
- * Returns the shared instance
- *
- * @return the shared instance
- */
- public static AndroidPlatformPlugin getDefault() {
- return sPlugin;
- }
-
- /**
- * Returns the Android project. This is the first project which has the PlatformNature.
- * @return the <code>IProject</code> of the Android project, or <code>null</code> if it was
- * not found.
- */
- public static IProject getDeviceProject() {
- // Get the list of projects for the current workspace.
- IWorkspace workspace = ResourcesPlugin.getWorkspace();
- IProject[] projects = workspace.getRoot().getProjects();
-
- for (IProject project : projects) {
- try {
- if (project.hasNature(PlatformNature.ID)) {
- return project;
- }
- } catch (CoreException e) {
- // Failed to get the nature for this project. Let's just ignore
- // it and move on to the next one.
- }
- }
-
- return null;
- }
-
- /**
- * Returns the OS path of the adb location.
- * @return the location of adb or null if it cannot be computed.
- */
- private String getOsAdbLocation() {
- if (mOsDeviceDirectory == null || mOsDeviceDirectory.length() == 0) {
- return null;
- }
-
- if (AndroidConstants.CURRENT_PLATFORM == AndroidConstants.PLATFORM_LINUX) {
- return mOsDeviceDirectory + "/out/host/linux-x86/bin/adb"; //$NON-NLS-1$
- } else if (AndroidConstants.CURRENT_PLATFORM == AndroidConstants.PLATFORM_DARWIN) {
- return mOsDeviceDirectory + "/out/host/darwin-x86/bin/adb"; //$NON-NLS-1$
- }
- return null;
- }
-
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/preferences/AndroidPreferencePage.java b/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/preferences/AndroidPreferencePage.java
deleted file mode 100644
index 8427bad..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/preferences/AndroidPreferencePage.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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.ide.eclipse.platform.preferences;
-
-import com.android.ide.eclipse.platform.AndroidPlatformPlugin;
-
-import org.eclipse.jface.preference.DirectoryFieldEditor;
-import org.eclipse.jface.preference.FieldEditorPreferencePage;
-import org.eclipse.ui.IWorkbench;
-import org.eclipse.ui.IWorkbenchPreferencePage;
-
-/**
- * This class represents a preference page that is contributed to the
- * Preferences dialog. By subclassing <samp>FieldEditorPreferencePage</samp>,
- * we can use the field support built into JFace that allows us to create a page
- * that is small and knows how to save, restore and apply itself.
- * <p>
- * This page is used to modify preferences only. They are stored in the
- * preference store that belongs to the main plug-in class. That way,
- * preferences can be accessed directly via the preference store.
- */
-public class AndroidPreferencePage extends FieldEditorPreferencePage implements
- IWorkbenchPreferencePage {
-
- public AndroidPreferencePage() {
- super(GRID);
- setPreferenceStore(AndroidPlatformPlugin.getDefault().getPreferenceStore());
- setDescription("Android Preferences");
- }
-
- /**
- * Creates the field editors. Field editors are abstractions of the common
- * GUI blocks needed to manipulate various types of preferences. Each field
- * editor knows how to save and restore itself.
- */
- @Override
- public void createFieldEditors() {
- addField(new DirectoryFieldEditor(AndroidPlatformPlugin.PREFS_DEVICE_DIRECTORY,
- "Location of //device", getFieldEditorParent()));
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
- */
- public void init(IWorkbench workbench) {
- }
-
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/ConvertToPlatformAction.java b/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/ConvertToPlatformAction.java
deleted file mode 100644
index 58d55e5..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/ConvertToPlatformAction.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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.ide.eclipse.platform.project;
-
-import com.android.ide.eclipse.platform.AndroidPlatformPlugin;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IProjectDescription;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IAdaptable;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jdt.core.IClasspathEntry;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.ui.IObjectActionDelegate;
-import org.eclipse.ui.IWorkbenchPart;
-
-import java.util.Iterator;
-
-/**
- * Converts a project created with the activity creator into an
- * Android project.
- */
-public class ConvertToPlatformAction implements IObjectActionDelegate {
-
- private ISelection mSelection;
-
- /*
- * (non-Javadoc)
- *
- * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
- */
- public void setActivePart(IAction action, IWorkbenchPart targetPart) {
- // pass
- }
-
- /*
- * (non-Javadoc)
- *
- * @see IActionDelegate#run(IAction)
- */
- public void run(IAction action) {
- if (mSelection instanceof IStructuredSelection) {
- for (Iterator<?> it = ((IStructuredSelection)mSelection).iterator(); it.hasNext();) {
- Object element = it.next();
- IProject project = null;
- if (element instanceof IProject) {
- project = (IProject)element;
- } else if (element instanceof IAdaptable) {
- project = (IProject)((IAdaptable)element).getAdapter(IProject.class);
- }
- if (project != null) {
- convertProject(project);
- }
- }
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see IActionDelegate#selectionChanged(IAction, ISelection)
- */
- public void selectionChanged(IAction action, ISelection selection) {
- this.mSelection = selection;
- }
-
- /**
- * Toggles sample nature on a project
- *
- * @param project to have sample nature added or removed
- */
- private void convertProject(final IProject project) {
- new Job("Convert Project") {
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- try {
- if (monitor != null) {
- monitor.beginTask(String.format(
- "Convert %1$s to Android", project.getName()), 5);
- }
-
- IProjectDescription description = project.getDescription();
- String[] natures = description.getNatureIds();
-
- // check if the project already has the android nature.
- for (int i = 0; i < natures.length; ++i) {
- if (PlatformNature.ID.equals(natures[i])) {
- // we shouldn't be here as the visibility of the item
- // is dependent on the project.
- return new Status(Status.WARNING, AndroidPlatformPlugin.PLUGIN_ID,
- "Project is already an Android Platform Project");
- }
- }
-
- // add the platform nature
- String[] newNatures = new String[natures.length + 1];
- System.arraycopy(natures, 0, newNatures, 1, natures.length);
- newNatures[0] = PlatformNature.ID;
-
- // set the new nature list in the project
- description.setNatureIds(newNatures);
- project.setDescription(description, null);
-
- IJavaProject javaProject = JavaCore.create(project);
- IClasspathEntry[] entries = javaProject.getRawClasspath();
-
- int n = entries.length;
- IClasspathEntry[] newEntries = new IClasspathEntry[n + 1];
- System.arraycopy(entries, 0, newEntries, 0, n);
- newEntries[n] = PlatformClasspathContainerInitializer.getContainerEntry();
-
- javaProject.setRawClasspath(newEntries, monitor);
-
- return Status.OK_STATUS;
- } catch (JavaModelException e) {
- return e.getJavaModelStatus();
- } catch (CoreException e) {
- return e.getStatus();
- } finally {
- if (monitor != null) {
- monitor.done();
- }
- }
- }
- }.schedule();
- }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/PlatformClasspathContainerInitializer.java b/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/PlatformClasspathContainerInitializer.java
deleted file mode 100644
index a54713c..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/PlatformClasspathContainerInitializer.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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.ide.eclipse.platform.project;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.jdt.core.ClasspathContainerInitializer;
-import org.eclipse.jdt.core.IClasspathContainer;
-import org.eclipse.jdt.core.IClasspathEntry;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.JavaCore;
-
-/**
- * Classpath container initializer responsible for binding {@link PlatformClasspathContainer} to
- * {@link IProject}s. Because any projects with this container force Eclipse to load the
- * plugin, this is a hack to make sure the android platform plugin is launched as soon as an
- * android project is opened.
- */
-public class PlatformClasspathContainerInitializer extends ClasspathContainerInitializer {
-
- /** The container id for the android framework jar file */
- private final static String CONTAINER_ID = "com.android.ide.eclipse.platform.DUMMY_CONTAINER"; //$NON-NLS-1$
-
- public PlatformClasspathContainerInitializer() {
- // pass
- }
-
- /**
- * Binds a classpath container to a {@link IClasspathContainer} for a given project,
- * or silently fails if unable to do so.
- * @param containerPath the container path that is the container id.
- * @param the project to bind
- */
- @Override
- public void initialize(IPath containerPath, IJavaProject project) throws CoreException {
- // pass
- }
-
- /**
- * Creates a new {@link IClasspathEntry} of type {@link IClasspathEntry#CPE_CONTAINER}
- * linking to the Android Framework.
- */
- public static IClasspathEntry getContainerEntry() {
- return JavaCore.newContainerEntry(new Path(CONTAINER_ID));
- }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/PlatformNature.java b/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/PlatformNature.java
deleted file mode 100644
index 884dc58..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/PlatformNature.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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.ide.eclipse.platform.project;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IProjectNature;
-import org.eclipse.core.runtime.CoreException;
-
-/**
- * Project nature for the Android Projects.
- */
-public class PlatformNature implements IProjectNature {
-
- public final static String ID = "com.android.ide.eclipse.platform.PlatformNature"; //$NON-NLS-1$
-
- /** the project this nature object is associated with */
- private IProject mProject;
-
- /**
- * Configures this nature for its project. This is called by the workspace
- * when natures are added to the project using
- * <code>IProject.setDescription</code> and should not be called directly
- * by clients. The nature extension id is added to the list of natures
- * before this method is called, and need not be added here.
- *
- * Exceptions thrown by this method will be propagated back to the caller of
- * <code>IProject.setDescription</code>, but the nature will remain in
- * the project description.
- *
- * In this implementation there is nothing to be done, since there's no builder associated
- * with this nature.
- *
- * @see org.eclipse.core.resources.IProjectNature#configure()
- * @throws CoreException if configuration fails.
- */
- public void configure() throws CoreException {
- // pass
- }
-
- /**
- * De-configures this nature for its project. This is called by the
- * workspace when natures are removed from the project using
- * <code>IProject.setDescription</code> and should not be called directly
- * by clients. The nature extension id is removed from the list of natures
- * before this method is called, and need not be removed here.
- *
- * Exceptions thrown by this method will be propagated back to the caller of
- * <code>IProject.setDescription</code>, but the nature will still be
- * removed from the project description.
- *
- * In this implementation there is nothing to be done, since there's no builder associated
- * with this nature.
- *
- * @see org.eclipse.core.resources.IProjectNature#deconfigure()
- * @throws CoreException if configuration fails.
- */
- public void deconfigure() throws CoreException {
- // pass
- }
-
- /**
- * Returns the project to which this project nature applies.
- *
- * @return the project handle
- * @see org.eclipse.core.resources.IProjectNature#getProject()
- */
- public IProject getProject() {
- return mProject;
- }
-
- /**
- * Sets the project to which this nature applies. Used when instantiating
- * this project nature runtime. This is called by
- * <code>IProject.create()</code> or
- * <code>IProject.setDescription()</code> and should not be called
- * directly by clients.
- *
- * @param project the project to which this nature applies
- * @see org.eclipse.core.resources.IProjectNature#setProject(org.eclipse.core.resources.IProject)
- */
- public void setProject(IProject project) {
- mProject = project;
- }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF b/tools/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF
index a121266..266008c 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF
@@ -2,18 +2,17 @@
Bundle-ManifestVersion: 2
Bundle-Name: Android Plugin Tests
Bundle-SymbolicName: com.android.ide.eclipse.tests
-Bundle-Version: 0.8.1.qualifier
+Bundle-Version: 0.9.0.qualifier
Bundle-Activator: com.android.ide.eclipse.tests.AndroidTestPlugin
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
org.eclipse.core.resources,
com.android.ide.eclipse.adt,
org.junit,
- com.android.ide.eclipse.common,
- com.android.ide.eclipse.editors,
org.eclipse.jdt.core,
org.eclipse.jdt.launching,
- org.eclipse.ui.views
+ org.eclipse.ui.views,
+ com.android.ide.eclipse.ddms
Eclipse-LazyStart: true
Bundle-Vendor: The Android Open Source Project
Bundle-ClassPath: kxml2-2.3.0.jar,
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/project/internal/StubSampleProjectCreationPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/wizards/newproject/StubSampleProjectCreationPage.java
similarity index 87%
rename from tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/project/internal/StubSampleProjectCreationPage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/wizards/newproject/StubSampleProjectCreationPage.java
index 3202c67..42f8df0 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/project/internal/StubSampleProjectCreationPage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/wizards/newproject/StubSampleProjectCreationPage.java
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 20078The Android Open Source Project
+ * Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ * http://www.eclipse.org/org/documents/epl-v10.php
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
@@ -13,9 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.android.ide.eclipse.adt.project.internal;
-
-import com.android.ide.eclipse.adt.project.internal.NewProjectCreationPage;
+package com.android.ide.eclipse.adt.wizards.newproject;
import java.io.File;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/project/internal/StubSampleProjectWizard.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/wizards/newproject/StubSampleProjectWizard.java
similarity index 91%
rename from tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/project/internal/StubSampleProjectWizard.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/wizards/newproject/StubSampleProjectWizard.java
index 49a853d..40cd636 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/project/internal/StubSampleProjectWizard.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/wizards/newproject/StubSampleProjectWizard.java
@@ -5,7 +5,7 @@
* may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
- * http://www.eclipse.org/org/documents/epl-v10.php
+ * http://www.eclipse.org/org/documents/epl-v10.php
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
@@ -13,10 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.android.ide.eclipse.adt.project.internal;
-
-import com.android.ide.eclipse.adt.project.internal.NewProjectCreationPage;
-import com.android.ide.eclipse.adt.project.internal.NewProjectWizard;
+package com.android.ide.eclipse.adt.wizards.newproject;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.operation.IRunnableWithProgress;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/SampleProjectTest.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/SampleProjectTest.java
index 5315db8..98817c6 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/SampleProjectTest.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/SampleProjectTest.java
@@ -5,7 +5,7 @@
* may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
- * http://www.eclipse.org/org/documents/epl-v10.php
+ * http://www.eclipse.org/org/documents/epl-v10.php
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
@@ -16,10 +16,9 @@
package com.android.ide.eclipse.tests.functests.sampleProjects;
import com.android.ide.eclipse.adt.project.ProjectHelper;
-import com.android.ide.eclipse.adt.project.internal.StubSampleProjectWizard;
+import com.android.ide.eclipse.adt.wizards.newproject.StubSampleProjectWizard;
import com.android.ide.eclipse.tests.FuncTestCase;
-
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/resources/AndroidJarLoaderTest.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/sdk/AndroidJarLoaderTest.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/resources/AndroidJarLoaderTest.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/sdk/AndroidJarLoaderTest.java
index 9d89d18..f3d9b79 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/resources/AndroidJarLoaderTest.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/sdk/AndroidJarLoaderTest.java
@@ -14,21 +14,19 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.resources;
+package com.android.ide.eclipse.adt.sdk;
-import com.android.ide.eclipse.adt.resources.LayoutParamsParser.IClass;
+import com.android.ide.eclipse.adt.sdk.IAndroidClassLoader.IClassDescriptor;
import com.android.ide.eclipse.tests.AdtTestData;
-import junit.framework.TestCase;
-
-import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
+import junit.framework.TestCase;
+
/**
* Unit Test for {@link FrameworkClassLoader}.
*
@@ -51,7 +49,7 @@
/** Preloads classes. They should load just fine. */
public final void testPreLoadClasses() throws Exception {
- mFrameworkClassLoader.preLoadClasses("jar.example.", null); //$NON-NLS-1$
+ mFrameworkClassLoader.preLoadClasses("jar.example.", null, null); //$NON-NLS-1$
HashMap<String, Class<?>> map = getPrivateClassCache();
assertEquals(0, map.size());
HashMap<String,byte[]> data = getPrivateEntryCache();
@@ -64,7 +62,7 @@
/** Preloads a class not in the JAR. Preloading does nothing in this case. */
public final void testPreLoadClasses_classNotFound() throws Exception {
- mFrameworkClassLoader.preLoadClasses("not.a.package.", null); //$NON-NLS-1$
+ mFrameworkClassLoader.preLoadClasses("not.a.package.", null, null); //$NON-NLS-1$
HashMap<String, Class<?>> map = getPrivateClassCache();
assertEquals(0, map.size());
HashMap<String,byte[]> data = getPrivateEntryCache();
@@ -108,7 +106,7 @@
}
public final void testFindClassesDerivingFrom() throws Exception {
- HashMap<String, ArrayList<IClass>> found =
+ HashMap<String, ArrayList<IClassDescriptor>> found =
mFrameworkClassLoader.findClassesDerivingFrom("jar.example.", new String[] { //$NON-NLS-1$
"jar.example.Class1", //$NON-NLS-1$
"jar.example.Class2" }); //$NON-NLS-1$
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/resources/LayoutParamsParserTest.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/sdk/LayoutParamsParserTest.java
similarity index 84%
rename from tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/resources/LayoutParamsParserTest.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/sdk/LayoutParamsParserTest.java
index 1a2ff9b..b66fcd6 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/resources/LayoutParamsParserTest.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/sdk/LayoutParamsParserTest.java
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.resources;
+package com.android.ide.eclipse.adt.sdk;
-import com.android.ide.eclipse.adt.resources.AndroidJarLoader.ClassWrapper;
-import com.android.ide.eclipse.adt.resources.LayoutParamsParser.IClass;
+import com.android.ide.eclipse.adt.sdk.AndroidJarLoader.ClassWrapper;
+import com.android.ide.eclipse.adt.sdk.IAndroidClassLoader.IClassDescriptor;
import com.android.ide.eclipse.common.resources.AttrsXmlParser;
import com.android.ide.eclipse.common.resources.ViewClassInfo;
import com.android.ide.eclipse.common.resources.ViewClassInfo.LayoutParamsInfo;
@@ -32,7 +32,7 @@
import junit.framework.TestCase;
/**
- * Test the inner private methods of FrameworkResourceParser.
+ * Test the inner private methods of PlatformDataParser.
*
* Convention: method names that start with an underscore are actually local wrappers
* that call private methods from {@link FrameworkResourceParser} using reflection.
@@ -47,9 +47,9 @@
}
@Override
- public HashMap<String, ArrayList<IClass>> findClassesDerivingFrom(
+ public HashMap<String, ArrayList<IClassDescriptor>> findClassesDerivingFrom(
String rootPackage, String[] superClasses) throws ClassFormatError {
- return new HashMap<String, ArrayList<IClass>>();
+ return new HashMap<String, ArrayList<IClassDescriptor>>();
}
}
@@ -70,8 +70,8 @@
mTopGroupClass = new ClassWrapper(mock_android.view.ViewGroup.class);
mTopLayoutParamsClass = new ClassWrapper(mock_android.view.ViewGroup.LayoutParams.class);
- mViewList = new ArrayList<IClass>();
- mGroupList = new ArrayList<IClass>();
+ mViewList = new ArrayList<IClassDescriptor>();
+ mGroupList = new ArrayList<IClassDescriptor>();
mViewMap = new TreeMap<String, ExtViewClassInfo>();
mGroupMap = new TreeMap<String, ExtViewClassInfo>();
mLayoutParamsMap = new HashMap<String, LayoutParamsInfo>();
@@ -131,16 +131,16 @@
//---- access to private methods
/** Calls the private constructor of the parser */
- private FrameworkResourceParser _Constructor(String osJarPath) throws Exception {
- Constructor<FrameworkResourceParser> constructor =
- FrameworkResourceParser.class.getDeclaredConstructor(String.class);
+ private AndroidTargetParser _Constructor(String osJarPath) throws Exception {
+ Constructor<AndroidTargetParser> constructor =
+ AndroidTargetParser.class.getDeclaredConstructor(String.class);
constructor.setAccessible(true);
return constructor.newInstance(osJarPath);
}
/** calls the private getLayoutClasses() of the parser */
private void _getLayoutClasses() throws Exception {
- Method method = FrameworkResourceParser.class.getDeclaredMethod("getLayoutClasses"); //$NON-NLS-1$
+ Method method = AndroidTargetParser.class.getDeclaredMethod("getLayoutClasses"); //$NON-NLS-1$
method.setAccessible(true);
method.invoke(mParser);
}
@@ -148,7 +148,7 @@
/** calls the private addGroup() of the parser */
private ViewClassInfo _addGroup(Class<?> groupClass) throws Exception {
Method method = LayoutParamsParser.class.getDeclaredMethod("addGroup", //$NON-NLS-1$
- IClass.class);
+ IClassDescriptor.class);
method.setAccessible(true);
return (ViewClassInfo) method.invoke(mParser, new ClassWrapper(groupClass));
}
@@ -156,7 +156,7 @@
/** calls the private addLayoutParams() of the parser */
private LayoutParamsInfo _addLayoutParams(Class<?> groupClass) throws Exception {
Method method = LayoutParamsParser.class.getDeclaredMethod("addLayoutParams", //$NON-NLS-1$
- IClass.class);
+ IClassDescriptor.class);
method.setAccessible(true);
return (LayoutParamsInfo) method.invoke(mParser, new ClassWrapper(groupClass));
}
@@ -164,17 +164,17 @@
/** calls the private getLayoutParamsInfo() of the parser */
private LayoutParamsInfo _getLayoutParamsInfo(Class<?> layoutParamsClass) throws Exception {
Method method = LayoutParamsParser.class.getDeclaredMethod("getLayoutParamsInfo", //$NON-NLS-1$
- IClass.class);
+ IClassDescriptor.class);
method.setAccessible(true);
return (LayoutParamsInfo) method.invoke(mParser, new ClassWrapper(layoutParamsClass));
}
/** calls the private findLayoutParams() of the parser */
- private IClass _findLayoutParams(Class<?> groupClass) throws Exception {
+ private IClassDescriptor _findLayoutParams(Class<?> groupClass) throws Exception {
Method method = LayoutParamsParser.class.getDeclaredMethod("findLayoutParams", //$NON-NLS-1$
- IClass.class);
+ IClassDescriptor.class);
method.setAccessible(true);
- return (IClass) method.invoke(mParser, new ClassWrapper(groupClass));
+ return (IClassDescriptor) method.invoke(mParser, new ClassWrapper(groupClass));
}
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/layout/UiElementPullParserTest.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/layout/UiElementPullParserTest.java
index 521bb62..1427eee 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/layout/UiElementPullParserTest.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/layout/UiElementPullParserTest.java
@@ -216,9 +216,6 @@
} catch (XmlPullParserException e) {
e.printStackTrace();
assertTrue(false);
- } catch (IOException e) {
- e.printStackTrace();
- assertTrue(false);
}
}
diff --git a/tools/eclipse/doBuild.sh b/tools/eclipse/scripts/build_plugins.sh
similarity index 83%
rename from tools/eclipse/doBuild.sh
rename to tools/eclipse/scripts/build_plugins.sh
index a0d8606..5f94ca0 100755
--- a/tools/eclipse/doBuild.sh
+++ b/tools/eclipse/scripts/build_plugins.sh
@@ -2,7 +2,7 @@
# build script for eclipse adt build on linux platform
#
-# Usage: doBuild <build_version>
+# Usage: development/tools/eclipse/scripts/build_plugins <build_version>
#
# It expects environment variable ECLIPSE_HOME to be defined to point to _your_
# version of Eclipse RCP (must have the WTP & GEF plugins available too.)
@@ -59,8 +59,10 @@
HOST=`uname`
[ "$HOST" == "Linux" ] || die "ERROR: This script is currently only supported on Linux platform"
-# Check which directory this is invoked from
-[ "${PWD: -13}" == "tools/eclipse" ] || dieWithUsage "Please run this script from the device/tools/eclipse directory"
+# Make sure this runs from the tools/eclipse plugin.
+D=`dirname "$0"`
+cd "$D/.."
+[ `basename "$PWD"` == "eclipse" ] || dieWithUsage "Please run this script from the device/tools/eclipse directory"
# check for number of parameters
[ $# -lt 1 ] && dieWithUsage "ERROR: Not enough parameters"
@@ -86,6 +88,8 @@
[ -f "$PID_FILE" ] && ECLIPSE_PID=`cat "$PID_FILE"`
fi
+echo "PWD=`pwd`"
+echo "ECLIPSE_HOME=$ECLIPSE_HOME"
#
# -- Site parameters and Build version --
@@ -124,7 +128,7 @@
# The "configuration directory" will hold the workspace for this build.
# If it contains old data the build may fail so we need to clean it first
# and create it if it doesn't exist.
-CONFIG_DIR="../../out/eclipse-configuration-$BUILD_VERSION"
+CONFIG_DIR="../../../out/eclipse-configuration-$BUILD_VERSION"
[ -d "$CONFIG_DIR" ] && rm -rfv "$CONFIG_DIR"
mkdir -p "$CONFIG_DIR"
@@ -173,8 +177,18 @@
echo " Build Config: $BUILDCONFIG"
echo " Config Dir: $CONFIG_DIR"
+# clean input directories to make sure there's nothing left from previous run
+
+rm -fv *.properties *.xml
+find . -name "@*" | xargs rm -rfv
+
+# Now execute the ant runner
+
+set +e # don't stop on errors anymore, we want to catch there here
+
java \
-jar $LAUNCHER \
+ -data "$CONFIG_DIR" \
-configuration "$CONFIG_DIR" \
-application org.eclipse.ant.core.antRunner \
-buildfile $BUILDFILE \
@@ -183,6 +197,21 @@
-DforceContextQualifier=$BUILD_VERSION \
-DECLIPSE_HOME=$ECLIPSE_HOME \
$SITE_PARAM
+RESULT=$?
+
+if [ "0" != "$RESULT" ]; then
+ echo "JAVA died with error code $RESULT"
+ echo "Dump of build config logs:"
+ for i in "$CONFIG_DIR"/*.log; do
+ if [ -f "$i" ]; then
+ echo "----------------------"
+ echo "--- $i"
+ echo "----------------------"
+ cat "$i"
+ echo
+ fi
+ done
+fi
#
# -- Cleanup
diff --git a/tools/eclipse/scripts/build_server.sh b/tools/eclipse/scripts/build_server.sh
index e30dbb8..39c8dcd 100755
--- a/tools/eclipse/scripts/build_server.sh
+++ b/tools/eclipse/scripts/build_server.sh
@@ -46,9 +46,10 @@
}
function check_params() {
- # This needs to run from //device
- [ `basename "$PWD"` == "device" ] || \
- die "Please execute $0 from the //device directory, not $PWD"
+ # This needs to run from the top android directory
+ # Automatically CD to the top android directory, whatever its name
+ D=`dirname "$0"`
+ cd "$D/../../../../" && echo "Switched to directory $PWD"
# The current Eclipse build has some Linux dependency in its config files
[ `uname` == "Linux" ] || die "This must run from a Linux box."
@@ -60,14 +61,12 @@
function build_libs() {
MAKE_OPT="-j8"
- echo "*** Building: make $MAKE_OPT dx ping ddms jarutils androidprefs layoutlib_api"
- make $MAKE_OPT dx ping ddms jarutils androidprefs layoutlib_api layoutlib_utils
+ echo "*** Building: make $MAKE_OPT dx ping ddms jarutils androidprefs layoutlib_api ninepatch sdklib sdkuilib"
+ make $MAKE_OPT dx ping ddms jarutils androidprefs layoutlib_api layoutlib_utils ninepatch sdklib sdkuilib
}
function build_plugin {
- cd tools/eclipse/scripts
- ./create_all_symlinks.sh
- cd .. # cd back to tools/eclipse
+ development/tools/eclipse/scripts/create_all_symlinks.sh
# Qualifier is "v" followed by date/time in YYYYMMDDHHSS format and the optional
# build number.
@@ -90,7 +89,7 @@
[ -d "$DEST_DIR/$BUILD_PREFIX" ] || rm -rfv "$DEST_DIR/$BUILD_PREFIX"
# Perform the Eclipse build and move the result in $DEST_DIR/android-build
- ./doBuild.sh $QUALIFIER $INTERNAL_BUILD -d "$DEST_DIR" -a "$BUILD_PREFIX"
+ development/tools/eclipse/scripts/build_plugins.sh $QUALIFIER $INTERNAL_BUILD -d "$DEST_DIR" -a "$BUILD_PREFIX"
# Cleanup
[ -d "$QUALIFIER" ] && rm -rfv "$QUALIFIER"
diff --git a/tools/eclipse/scripts/create_adt_symlinks.sh b/tools/eclipse/scripts/create_adt_symlinks.sh
index 4974432..557c4d9 100755
--- a/tools/eclipse/scripts/create_adt_symlinks.sh
+++ b/tools/eclipse/scripts/create_adt_symlinks.sh
@@ -1,42 +1,50 @@
#!/bin/bash
function die() {
- echo "Error: $*"
- exit 1
+ echo "Error: $*"
+ exit 1
}
set -e # fail early
-# This may run either from the //device directory or from the
-# eclipse/script directory. Allow for both.
-D="device/tools/eclipse/scripts"
-[ -d "$D" ] && cd "$D"
-[ -d "../$D" ] && cd "../$D"
+# CD to the top android directory
+D=`dirname "$0"`
+cd "$D/../../../../"
-cd ../plugins/com.android.ide.eclipse.adt
+DEST="development/tools/eclipse/plugins/com.android.ide.eclipse.adt"
+# computes "../.." from DEST to here (in /android)
+BACK=`echo $DEST | sed 's@[^/]*@..@g'`
+
+LIBS="sdkstats jarutils androidprefs layoutlib_api layoutlib_utils ninepatch sdklib sdkuilib"
+
+echo "make java libs ..."
+make -j3 showcommands $LIBS || die "ADT: Fail to build one of $LIBS."
+
+echo "Copying java libs to $DEST"
+
HOST=`uname`
if [ "$HOST" == "Linux" ]; then
- ln -svf ../../../../out/host/linux-x86/framework/jarutils.jar .
- ln -svf ../../../../out/host/linux-x86/framework/androidprefs.jar .
+ for LIB in $LIBS; do
+ ln -svf $BACK/out/host/linux-x86/framework/$LIB.jar "$DEST/"
+ done
+ ln -svf $BACK/out/host/linux-x86/framework/kxml2-2.3.0.jar "$DEST/"
+
elif [ "$HOST" == "Darwin" ]; then
- ln -svf ../../../../out/host/darwin-x86/framework/jarutils.jar .
- ln -svf ../../../../out/host/darwin-x86/framework/androidprefs.jar .
+ for LIB in $LIBS; do
+ ln -svf $BACK/out/host/darwin-x86/framework/$LIB.jar "$DEST/"
+ done
+ ln -svf $BACK/out/host/darwin-x86/framework/kxml2-2.3.0.jar "$DEST/"
+
elif [ "${HOST:0:6}" == "CYGWIN" ]; then
+ for LIB in $LIBS; do
+ cp -vf out/host/windows-x86/framework/$LIB.jar "$DEST/"
+ done
- DEVICE_DIR="../../../.."
- echo "make java libs ..."
- ( cd "$DEVICE_DIR" &&
- make -j3 showcommands jarutils androidprefs ) || \
- die "Define javac and retry."
+ if [ ! -f "$DEST/kxml2-2.3.0.jar" ]; then
+ cp -v "prebuilt/common/kxml2/kxml2-2.3.0.jar" "$DEST/"
+ fi
- for DIR in "$PWD" ; do
- echo "Copying java libs to $DIR"
- for JAR in jarutils.jar androidprefs.jar ; do
- cp -vf "$DEVICE_DIR/out/host/windows-x86/framework/$JAR" "$DIR"
- done
- done
-
- chmod a+rx *.jar
+ chmod -v a+rx "$DEST"/*.jar
else
- echo "Unsupported platform ($HOST). Nothing done."
+ echo "Unsupported platform ($HOST). Nothing done."
fi
diff --git a/tools/eclipse/scripts/create_all_symlinks.sh b/tools/eclipse/scripts/create_all_symlinks.sh
index fc9766f..8508343 100755
--- a/tools/eclipse/scripts/create_all_symlinks.sh
+++ b/tools/eclipse/scripts/create_all_symlinks.sh
@@ -3,30 +3,25 @@
echo "### $0 executing"
function die() {
- echo "Error: $*"
- exit 1
+ echo "Error: $*"
+ exit 1
}
-D="device/tools/eclipse/scripts"
-if [ -d "../$D" ]; then
- cd "../$D"
-else
- [ "${PWD: -28}" == "$D" ] || die "Please execute this from the $D directory"
-fi
+# CD to the top android directory
+D=`dirname "$0"`
+cd "$D/../../../../"
+
+DEST="development/tools/eclipse/scripts"
set -e # fail early
echo ; echo "### ADT ###" ; echo
-./create_adt_symlinks.sh "$*"
-echo ; echo "### COMMON ###" ; echo
-./create_common_symlinks.sh "$*"
-echo ; echo "### EDITORS ###" ; echo
-./create_editors_symlinks.sh "$*"
+$DEST/create_adt_symlinks.sh "$*"
echo ; echo "### DDMS ###" ; echo
-./create_ddms_symlinks.sh "$*"
+$DEST/create_ddms_symlinks.sh "$*"
echo ; echo "### TEST ###" ; echo
-./create_test_symlinks.sh "$*"
+$DEST/create_test_symlinks.sh "$*"
echo ; echo "### BRIDGE ###" ; echo
-./create_bridge_symlinks.sh "$*"
+$DEST/create_bridge_symlinks.sh "$*"
echo "### $0 done"
diff --git a/tools/eclipse/scripts/create_bridge_symlinks.sh b/tools/eclipse/scripts/create_bridge_symlinks.sh
index f01a89e..605ef63 100755
--- a/tools/eclipse/scripts/create_bridge_symlinks.sh
+++ b/tools/eclipse/scripts/create_bridge_symlinks.sh
@@ -1,47 +1,38 @@
#!/bin/bash
function die() {
- echo "Error: $*"
- exit 1
+ echo "Error: $*"
+ exit 1
}
set -e # fail early
-# This may run either from the //device directory or from the
-# eclipse/script directory. Allow for both.
-D="device/tools/eclipse/scripts"
-[ -d "$D" ] && cd "$D"
-[ -d "../$D" ] && cd "../$D"
-
-cd ../../layoutlib
+# CD to the top android directory
+D=`dirname "$0"`
+cd "$D/../../../../"
HOST=`uname`
if [ "$HOST" == "Linux" ]; then
- echo # nothing to do
+ echo # nothing to do
+
elif [ "$HOST" == "Darwin" ]; then
- echo # nothing to do
+ echo # nothing to do
+
elif [ "${HOST:0:6}" == "CYGWIN" ]; then
- if [ "x$1" == "x" ]; then
- echo "Usage: $0 sdk/tools/lib/"
- echo "Argument 1 should be the path to the jars you want to copy. "
- echo " e.g. android_sdk_windows_NNN/tools/lib/ "
- echo "This will be used to update layout.lib after it has been built here."
- exit 1
- fi
+ if [ "x$1" == "x" ] || [ `basename "$1"` != "layoutlib.jar" ]; then
+ echo "Usage: $0 sdk/platforms/xxx/data/layoutlib.jar"
+ echo "Argument 1 should be the path to the layoutlib.jar that should be updated."
+ exit 1
+ fi
- DEVICE_DIR="../../"
- echo "make java libs ..."
- ( cd "$DEVICE_DIR" &&
- make -j3 showcommands layoutlib ninepatch ) || \
- die "Define javac and retry."
+ LIBS="layoutlib ninepatch"
+ echo "Make java libs: $LIBS"
+ make -j3 showcommands $LIBS || die "Bridge: Failed to build one of $LIBS."
- for DIR in "$PWD" "$1" ; do
- echo "Copying java libs to $DIR"
- for JAR in ninepatch.jar layoutlib.jar ; do
- cp -vf "$DEVICE_DIR/out/host/windows-x86/framework/$JAR" "$DIR"
- done
- done
+ echo "Updating your SDK in $1"
+ cp -vf "out/host/windows-x86/framework/layoutlib.jar" "$1"
+ chmod -v a+rx "$1"
else
- echo "Unsupported platform ($HOST). Nothing done."
+ echo "Unsupported platform ($HOST). Nothing done."
fi
diff --git a/tools/eclipse/scripts/create_common_symlinks.sh b/tools/eclipse/scripts/create_common_symlinks.sh
deleted file mode 100755
index 7726afc..0000000
--- a/tools/eclipse/scripts/create_common_symlinks.sh
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/bash
-function die() {
- echo "Error: $*"
- exit 1
-}
-
-set -e # fail early
-
-# This may run either from the //device directory or from the
-# eclipse/script directory. Allow for both.
-D="device/tools/eclipse/scripts"
-[ -d "$D" ] && cd "$D"
-[ -d "../$D" ] && cd "../$D"
-
-cd ../plugins/com.android.ide.eclipse.common
-HOST=`uname`
-if [ "$HOST" == "Linux" ]; then
- ln -svf ../../../../out/host/linux-x86/framework/sdkstats.jar .
- ln -svf ../../../../out/host/linux-x86/framework/androidprefs.jar .
-elif [ "$HOST" == "Darwin" ]; then
- ln -svf ../../../../out/host/darwin-x86/framework/sdkstats.jar .
- ln -svf ../../../../out/host/darwin-x86/framework/androidprefs.jar .
-elif [ "${HOST:0:6}" == "CYGWIN" ]; then
-
- DEVICE_DIR="../../../.."
- echo "make java libs ..."
- ( cd "$DEVICE_DIR" &&
- make -j3 sdkstats androidprefs ) || \
- die "Define javac and retry."
-
- for DIR in "$PWD" ; do
- echo "Copying java libs to $DIR"
- for JAR in sdkstats.jar androidprefs.jar ; do
- cp -vf "$DEVICE_DIR/out/host/windows-x86/framework/$JAR" "$DIR"
- chmod a+rx "$DIR/$JAR"
- done
- done
-
-else
- echo "Unsupported platform ($HOST). Nothing done."
-fi
-
diff --git a/tools/eclipse/scripts/create_ddms_symlinks.sh b/tools/eclipse/scripts/create_ddms_symlinks.sh
index 5b2e45b..276cf9b 100755
--- a/tools/eclipse/scripts/create_ddms_symlinks.sh
+++ b/tools/eclipse/scripts/create_ddms_symlinks.sh
@@ -4,58 +4,76 @@
# Run this from device/tools/eclipse/scripts
#----------------------------------------------------------------------------|
-CMD="ln -svf"
-DIR="ln -svf"
+set -e
+
HOST=`uname`
if [ "${HOST:0:6}" == "CYGWIN" ]; then
- CMD="cp -rvf"
- DIR="rsync -avW --delete-after"
+ # We can't use symlinks under Cygwin
+
+ function cpfile { # $1=dest $2=source
+ cp -fv $2 $1/
+ }
+
+ function cpdir() { # $1=dest $2=source
+ rsync -avW --delete-after $2 $1
+ }
+
+else
+ # For all other systems which support symlinks
+
+ # computes the "reverse" path, e.g. "a/b/c" => "../../.."
+ function back() {
+ echo $1 | sed 's@[^/]*@..@g'
+ }
+
+ function cpfile { # $1=dest $2=source
+ ln -svf `back $1`/$2 $1/
+ }
+
+ function cpdir() { # $1=dest $2=source
+ ln -svf `back $1`/$2 $1
+ }
fi
-cd ../plugins/com.android.ide.eclipse.ddms
-mkdir -p libs
-cd libs
-$CMD ../../../../../prebuilt/common/jfreechart/jcommon-1.0.12.jar .
-$CMD ../../../../../prebuilt/common/jfreechart/jfreechart-1.0.9.jar .
-$CMD ../../../../../prebuilt/common/jfreechart/jfreechart-1.0.9-swt.jar .
-
-cd ../src/com/android
-$DIR ../../../../../../ddms/libs/ddmlib/src/com/android/ddmlib .
-$DIR ../../../../../../ddms/libs/ddmuilib/src/com/android/ddmuilib .
-
-# goes back to the icons directory
-cd ../../../icons/
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/debug-attach.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/debug-wait.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/debug-error.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/device.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/emulator.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/heap.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/thread.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/empty.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/warning.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/d.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/e.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/i.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/v.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/w.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/add.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/delete.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/edit.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/save.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/push.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/pull.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/clear.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/up.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/down.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/gc.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/halt.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/load.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/importBug.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/play.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/pause.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/forward.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/backward.png .
+# CD to the top android directory
+D=`dirname "$0"`
+cd "$D/../../../../"
+BASE="development/tools/eclipse/plugins/com.android.ide.eclipse.ddms"
+
+DEST=$BASE/libs
+mkdir -p $DEST
+for i in prebuilt/common/jfreechart/*.jar; do
+ cpfile $DEST $i
+done
+
+DEST=$BASE/src/com/android
+mkdir -p $DEST
+for i in development/tools/ddms/libs/ddmlib/src/com/android/ddmlib \
+ development/tools/ddms/libs/ddmuilib/src/com/android/ddmuilib ; do
+ cpdir $DEST $i
+done
+
+DEST=$BASE/icons
+mkdir -p $DEST
+for i in \
+ add.png \
+ backward.png \
+ clear.png \
+ d.png debug-attach.png debug-error.png debug-wait.png delete.png device.png down.png \
+ e.png edit.png empty.png emulator.png \
+ forward.png \
+ gc.png \
+ heap.png halt.png \
+ i.png importBug.png \
+ load.png \
+ pause.png play.png pull.png push.png \
+ save.png \
+ thread.png \
+ up.png \
+ v.png \
+ w.png warning.png ; do
+ cpfile $DEST development/tools/ddms/libs/ddmuilib/src/resources/images/$i
+done
diff --git a/tools/eclipse/scripts/create_editors_symlinks.sh b/tools/eclipse/scripts/create_editors_symlinks.sh
deleted file mode 100755
index 2f26ac4..0000000
--- a/tools/eclipse/scripts/create_editors_symlinks.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/bash
-function die() {
- echo "Error: $*"
- exit 1
-}
-
-cd ../plugins/com.android.ide.eclipse.editors
-HOST=`uname`
-if [ "$HOST" == "Linux" ]; then
- ln -svf ../../../../out/host/linux-x86/framework/layoutlib_api.jar .
- ln -svf ../../../../out/host/linux-x86/framework/layoutlib_utils.jar .
- ln -svf ../../../../out/host/linux-x86/framework/kxml2-2.3.0.jar .
- ln -svf ../../../../out/host/linux-x86/framework/ninepatch.jar .
-elif [ "$HOST" == "Darwin" ]; then
- ln -svf ../../../../out/host/darwin-x86/framework/layoutlib_api.jar .
- ln -svf ../../../../out/host/darwin-x86/framework/layoutlib_utils.jar .
- ln -svf ../../../../out/host/darwin-x86/framework/kxml2-2.3.0.jar .
- ln -svf ../../../../out/host/darwin-x86/framework/ninepatch.jar .
-elif [ "${HOST:0:6}" == "CYGWIN" ]; then
- set -e # fail early
- DEVICE_DIR="../../../../"
- echo "make java libs ..."
- ( cd "$DEVICE_DIR" &&
- make -j3 showcommands layoutlib_api layoutlib_utils ninepatch ) || \
- die "Define javac and 'make layoutlib_api ninepatch' from device."
-
- echo "Copying java libs to $PWD"
- for JAR in layoutlib_api.jar layoutlib_utils.jar ninepatch.jar ; do
- cp -vf "$DEVICE_DIR/out/host/windows-x86/framework/$JAR" .
- done
- if [ ! -f "./kxml2-2.3.0.jar" ]; then
- cp -v $DEVICE_DIR/prebuilt/common/kxml2/kxml2-2.3.0.jar .
- chmod -v a+rx *.jar
- fi
-
-else
- echo "Unsupported platform ($HOST). Nothing done."
-fi
-
diff --git a/tools/eclipse/scripts/create_test_symlinks.sh b/tools/eclipse/scripts/create_test_symlinks.sh
index 110539a..1479e04 100755
--- a/tools/eclipse/scripts/create_test_symlinks.sh
+++ b/tools/eclipse/scripts/create_test_symlinks.sh
@@ -1,24 +1,48 @@
#!/bin/bash
-cd ../plugins/com.android.ide.eclipse.tests
+
+set -e
+
+# CD to the top android directory
+D=`dirname "$0"`
+cd "$D/../../../../"
+
+# computes relative ".." paths from $1 to here (in /android)
+function back() {
+ echo $1 | sed 's@[^/]*@..@g'
+}
+
+BASE="development/tools/eclipse/plugins/com.android.ide.eclipse.tests"
+DEST=$BASE
+BACK=`back $DEST`
+
+
HOST=`uname`
if [ "$HOST" == "Linux" ]; then
- ln -svf ../../../../out/host/linux-x86/framework/kxml2-2.3.0.jar .
+ DIR="ln -svf"
+ ln -svf $BACK/out/host/linux-x86/framework/kxml2-2.3.0.jar "$DEST/"
+
elif [ "$HOST" == "Darwin" ]; then
- ln -svf ../../../../out/host/darwin-x86/framework/kxml2-2.3.0.jar .
+ DIR="ln -svf"
+ ln -svf $BACK/out/host/darwin-x86/framework/kxml2-2.3.0.jar "$DEST/"
+
elif [ "${HOST:0:6}" == "CYGWIN" ]; then
- if [ "x$1" == "x" ]; then
- echo "Usage: $0 <path to jars>"
- echo "Argument 1 should be the path to the jars you want to copy. "
- echo " e.g. android_sdk_windows_NNN/tools/lib/ "
- echo "(since you can't rebuild them under Windows, you need prebuilt ones "
- echo " from an SDK drop or a Linux/Mac)"
- exit 1
- fi
- if [ ! -f "kxml2-2.3.0.jar" ]; then
- wget -O "kxml2-2.3.0.jar" "http://internap.dl.sourceforge.net/sourceforge/kxml/kxml2-2.3.0.jar"
- chmod a+rx *.jar
- fi
+ DIR="rsync -avW --delete-after"
+ JAR="kxml2-2.3.0.jar"
+ if [ ! -f "$DEST/$JAR" ]; then
+ # Get the jar from ADT if we can, otherwise download it.
+ if [ -f "$DEST/../com.android.ide.eclipse.adt/$JAR" ]; then
+ cp "$DEST/../com.android.ide.eclipse.adt/$JAR" "$DEST/$JAR"
+ else
+ wget -O "$DEST/$JAR" "http://internap.dl.sourceforge.net/sourceforge/kxml/$JAR"
+ fi
+ chmod a+rx "$DEST/$JAR"
+ fi
else
- echo "Unsupported platform ($HOST). Nothing done."
+ echo "Unsupported platform ($HOST). Nothing done."
fi
+# create link to ddmlib tests
+DEST=$BASE/unittests/com/android
+BACK=`back $DEST`
+$DIR $BACK/development/tools/ddms/libs/ddmlib/tests/src/com/android/ddmlib $DEST/
+
diff --git a/tools/eclipse/scripts/update_version.sh b/tools/eclipse/scripts/update_version.sh
new file mode 100644
index 0000000..a288965
--- /dev/null
+++ b/tools/eclipse/scripts/update_version.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+OLD="$1"
+NEW="$2"
+
+# sanity check in input args
+if [ -z "$OLD" ] || [ -z "$NEW" ]; then
+ cat <<EOF
+Usage: $0 <old> <new>
+Changes the ADT plugin revision number.
+Example:
+ cd tools/eclipse
+ scripts/update_version.sh 0.1.2 0.2.3
+EOF
+ exit 1
+fi
+
+# sanity check on current dir
+if [ `basename "$PWD"` != "eclipse" ]; then
+ echo "Please run this from tools/eclipse."
+ exit 1
+fi
+
+# quote dots for regexps
+OLD="${OLD//./\.}"
+NEW="${NEW//./\.}"
+
+# Find all the files with the old pattern, except changes.txt and
+# p4 edit them. Skip that if there's no p4 in path.
+if which g4 1>/dev/null 2>/dev/null ; then
+ grep -rl "$OLD" * | grep -E "\.xml$|\.MF$" | xargs -n 5 g4 edit
+fi
+
+# Now find the same files but this time use sed to replace in-place with
+# the new pattern. Old files get backuped with the .old extension.
+grep -rl "$OLD" * | grep -E "\.xml$|\.MF$" | xargs -n 1 sed -i.old "s/$OLD/$NEW/g"
+
diff --git a/tools/eclipse/sites/external/site.xml b/tools/eclipse/sites/external/site.xml
index be123f6..e98a988 100644
--- a/tools/eclipse/sites/external/site.xml
+++ b/tools/eclipse/sites/external/site.xml
@@ -3,10 +3,7 @@
<description url="https://dl-ssl.google.com/android/eclipse/">
Update Site for Android Development Toolkit
</description>
- <feature url="features/com.android.ide.eclipse.adt_0.8.1.qualifier.jar" id="com.android.ide.eclipse.adt" version="0.8.1.qualifier">
- <category name="developer"/>
- </feature>
- <feature url="features/com.android.ide.eclipse.editors_0.8.1.qualifier.jar" id="com.android.ide.eclipse.editors" version="0.8.1.qualifier">
+ <feature url="features/com.android.ide.eclipse.adt_0.9.0.qualifier.jar" id="com.android.ide.eclipse.adt" version="0.9.0.qualifier">
<category name="developer"/>
</feature>
<category-def name="developer" label="Developer Tools">
diff --git a/tools/eclipse/sites/internal/site.xml b/tools/eclipse/sites/internal/site.xml
index 3263886..a7ef628 100644
--- a/tools/eclipse/sites/internal/site.xml
+++ b/tools/eclipse/sites/internal/site.xml
@@ -3,17 +3,10 @@
<description url="https://android.corp.google.com/adt/">
Update Site for Android Development Toolkit
</description>
- <feature url="features/com.android.ide.eclipse.adt_0.8.1.qualifier.jar" id="com.android.ide.eclipse.adt" version="0.8.1.qualifier">
+ <feature url="features/com.android.ide.eclipse.adt_0.9.0.qualifier.jar" id="com.android.ide.eclipse.adt" version="0.9.0.qualifier">
<category name="developer"/>
</feature>
- <feature url="features/com.android.ide.eclipse.editors_0.8.1.qualifier.jar" id="com.android.ide.eclipse.editors" version="0.8.1.qualifier">
- <category name="developer"/>
- <category name="platform"/>
- </feature>
- <feature url="features/com.android.ide.eclipse.platform_0.8.1.qualifier.jar" id="com.android.ide.eclipse.platform" version="0.8.1.qualifier">
- <category name="platform"/>
- </feature>
- <feature url="features/com.android.ide.eclipse.tests_0.8.1.qualifier.jar" id="com.android.ide.eclipse.tests" version="0.8.1.qualifier">
+ <feature url="features/com.android.ide.eclipse.tests_0.9.0.qualifier.jar" id="com.android.ide.eclipse.tests" version="0.9.0.qualifier">
<category name="test"/>
</feature>
<category-def name="developer" label="Application Developer Tools">
@@ -21,11 +14,6 @@
Features that add Android support to Eclipse for application developers.
</description>
</category-def>
- <category-def name="platform" label="Platform Developer Tools">
- <description>
- Features that add Android support to Eclipse for platform developers.
- </description>
- </category-def>
<category-def name="test" label="Plugin Developer Tests">
<description>
Tests for the other Android plugins
diff --git a/tools/findunused/findunusedresources b/tools/findunused/findunusedresources
index ff91e20..85e15b2 100755
--- a/tools/findunused/findunusedresources
+++ b/tools/findunused/findunusedresources
@@ -20,7 +20,7 @@
apps=$1
if [ "$apps" == "" ]
then
- apps=$ANDROID_BUILD_TOP/apps/*
+ apps=$ANDROID_BUILD_TOP/packages/apps/*
fi
for app in $apps
@@ -31,7 +31,7 @@
rDotJava=$(find out/target/common/obj/APPS/${appname}_intermediates/ -name R.java)
for i in $(cat $rDotJava | grep "\w*=0x\d*" | sed 's/ *public static final int //' | sed 's/=0x.*//')
do
- echo $i $(grep -Rw R\\..*\\.$i\\\|@style/$i\\\|@drawable/$i\\\|@color/$i\\\|@xml/$i\\\|@layout/$i\\\|@menu/$i\\\|@+id/$i\\\|@array/$i\\\|@string/$i $app | wc -l)
+ echo $i $(grep -Rw R\\..*\\.$i\\\|@style/$i\\\|@drawable/$i\\\|@anim/$i\\\|@color/$i\\\|@xml/$i\\\|@layout/$i\\\|@menu/$i\\\|@+id/$i\\\|@array/$i\\\|@string/$i $app | wc -l)
done | grep " 0$" | {
if [ "$showall" == "yes" ]
then
diff --git a/tools/findunused/findunusedstrings b/tools/findunused/findunusedstrings
index 7bf0119..a54b060 100755
--- a/tools/findunused/findunusedstrings
+++ b/tools/findunused/findunusedstrings
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
if [ "$1" == "-h" ]
then
@@ -20,7 +20,7 @@
apps=$1
if [ "$apps" == "" ]
then
- apps=$ANDROID_BUILD_TOP/apps/*
+ apps=$ANDROID_BUILD_TOP/packages/apps/*
fi
for app in $apps
@@ -28,9 +28,9 @@
if [ -d $app/res ]
then
pushd $app > /dev/null
- for i in $(grep -R "string name=" res | sed 's/.*<string name="//'|sed 's/".*$//')
+ for i in $(grep -R "\(string\|plurals\) name=" res | sed 's/.*<\(string\|plurals\) name="//'|sed 's/".*$//'|sort -u)
do
- echo $i $(grep -Rw R.string.$i\\\|@string/$i .|wc -l)
+ echo $i $(grep -Rw R.plurals.$i\\\|R.string.$i\\\|@string/$i .|wc -l)
done | grep ' 0$' | {
if [ "$showall" == "yes" ]
then
diff --git a/tools/idegen/Android.mk b/tools/idegen/Android.mk
new file mode 100644
index 0000000..e76e5b4
--- /dev/null
+++ b/tools/idegen/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_MODULE:= idegen
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
diff --git a/tools/idegen/README b/tools/idegen/README
new file mode 100644
index 0000000..1f773d8
--- /dev/null
+++ b/tools/idegen/README
@@ -0,0 +1,80 @@
+IDEGen automatically generates Android IDE configurations for IntelliJ IDEA
+and Eclipse. Your IDE should be able to compile everything in a reasonable
+amount of time with no errors.
+
+If you're using IntelliJ...
+
+ If this is your first time using IDEGen...
+
+ IDEA needs a lot of memory. Add "-Xms748m -Xmx748m" to your VM options
+ in "IDEA_HOME/bin/idea.vmoptions" on Linux or
+ "IntelliJ IDEA.app/Contents/Info.plist" on OS X.
+
+ Create a JDK configuration named "1.5 (No Libraries)" by adding a new
+ JDK like you normally would and then removing all of the jar entries
+ under the "Classpath" tab. This will ensure that you only get access to
+ Android's core libraries and not those from your desktop VM.
+
+ From the project's root directory...
+
+ Repeat these steps after each sync...
+
+ 1) make (to produce generated .java source)
+ 2) development/tools/idegen/idegen.sh
+ 3) Open android.ipr in IntelliJ. If you already have the project open,
+ hit the sync button in IntelliJ, and it will automatically detect the
+ updated configuration.
+
+ If you get unexpected compilation errors from IntelliJ, try running
+ "Build -> Rebuild Project". Sometimes IntelliJ gets confused after the
+ project changes significantly.
+
+If you're using Eclipse...
+
+ If this is your first time using IDEGen...
+
+ Edit eclipse.ini ("Eclipse.app/Contents/MacOS/eclipse.ini" on OS X) and
+ add "-Xms748m -Xmx748m" to your VM options.
+
+ Configure a JRE named "1.5 (No Libraries)" under "Preferences -> Java ->
+ Installed JREs". Remove all of the jar entries underneath "JRE system
+ libraries". Eclipse will not let you save your configuration unless at
+ least one jar is present, so include a random jar that won't get in the
+ way.
+
+ From the project's root directory...
+
+ Repeat these steps after each sync...
+
+ 1) make (to produce generated .java source)
+ 2) development/tools/idegen/idegen.sh
+ 3) Import the project root directory into your Eclipse workspace. If you
+ already have the project open, simply refresh it (F5).
+
+Excluding source roots and jars
+
+ IDEGen keeps an exclusion list in the "excluded-paths" file. This file
+ has one regular expression per line that matches paths (relative to the
+ project root) that should be excluded from the IDE configuration. We
+ use Java's regular expression parser (see java.util.regex.Parser).
+
+ You can create your own additional exclusion list by creating an
+ "excluded-paths" file in the project's root directory. For example, you
+ might exclude all apps except the Browser in your IDE configuration with
+ this regular expression: "^packages/apps/(?!Browser)".
+
+Controlling source root ordering (Eclipse)
+
+ You may want some source roots to come before others in Eclipse. Simply
+ create a file named "path-precedence" in your project's root directory.
+ Each line in the file is a regular expression that matches a source root
+ path (relative to the project's root directory). If a given source root's
+ path matches a regular expression that comes earlier in the file, that
+ source root will come earlier in the generated configuration. If a source
+ root doesn't match any of the expressions in the file, it will come last,
+ so you effectively have an implicit ".*" rule at the end of the file.
+
+ For example, if you want your applications's source root to come first,
+ you might add an expression like "^packages/apps/MyApp/src$" to the top
+ of the "path-precedence" file. To make source roots under ./out come last,
+ add "^(?!out/)" (which matches all paths that don't start with "out/").
\ No newline at end of file
diff --git a/tools/idegen/excluded-paths b/tools/idegen/excluded-paths
new file mode 100644
index 0000000..35280ad
--- /dev/null
+++ b/tools/idegen/excluded-paths
@@ -0,0 +1,64 @@
+# Default Idegen excluded paths file. Contains regular expressions, one per
+# line, which match paths of directories and .jar files that should be excluded
+# from the IDE configuration.
+#
+# We want to exclude as litte as possible by default, so it's important to
+# document the reason for each exclusion.
+#
+# Developers can also create an 'excluded-paths' file in the project's root
+# directory and add their own excludes to slim down their build.
+#
+# Currently, we lump all the .java files together into one big module, so you
+# can't have two classes with the same name at once. In the future, we'll
+# generate individual modules, each with their own dependencies, much like the
+# build, so we won't have to worry about duplicate names any more than the
+# build does.
+#
+# Note: Google-specific excludes go in vendor/google/excluded-paths.
+
+# Generated API stubs. We only want the originals in our IDE.
+android_stubs
+
+# Extra copies of JUnit.
+^dalvik/dx/src/junit$
+^dalvik/libcore/luni/src/test/java/junit$
+
+# Duplicate R.java files. We'll keep the versions from the "intermediates"
+# directories.
+^out/target/common/R$
+
+# Not actually built. Also disabled in make file.
+^development/samples/MySampleRss$
+^development/apps/OBJViewer$
+^packages/apps/IM/samples/PluginDemo$
+
+# We don't currently support development tool source code. Development tools
+# typically have their own IDE configurations anyway.
+#
+# The main problem is that the development tools are meant to run against a
+# fully featured desktop VM while almost everything in our IDE configuration
+# is meant to run against Android's more limited APIs. Mixing the two
+# environments in one IDE configuration doesn't work well.
+^development/tools$
+^external/jdiff$
+^external/emma$
+^external/clearsilver$
+layoutlib
+^prebuilt/.*\.jar$
+^dalvik/.*\.jar$
+^build/tools/droiddoc$
+
+# Each test has a Main.java in the default package, so they conflict with
+# each other.
+^dalvik/tests$
+
+# We can only support one policy impl at a time.
+^frameworks/policies/base/mid$
+#^frameworks/policies/base/phone$
+
+# We don't want compiled jars.
+^out/.*\.jar$
+
+# This directory contains only an R.java file which is the same as the one in
+# Camera_intermediates.
+^out/target/common/obj/APPS/CameraTests_intermediates$
diff --git a/tools/idegen/idegen.iml b/tools/idegen/idegen.iml
new file mode 100644
index 0000000..04646ae
--- /dev/null
+++ b/tools/idegen/idegen.iml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module relativePaths="true" type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/classes" />
+ <output-test url="file://$MODULE_DIR$/classes" />
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+
diff --git a/tools/idegen/idegen.ipr b/tools/idegen/idegen.ipr
new file mode 100644
index 0000000..00cf4fd
--- /dev/null
+++ b/tools/idegen/idegen.ipr
@@ -0,0 +1,330 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project relativePaths="false" version="4">
+ <component name="AntConfiguration">
+ <defaultAnt bundledAnt="true" />
+ </component>
+ <component name="BuildJarProjectSettings">
+ <option name="BUILD_JARS_ON_MAKE" value="false" />
+ </component>
+ <component name="CodeStyleProjectProfileManger">
+ <option name="PROJECT_PROFILE" />
+ <option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
+ </component>
+ <component name="CodeStyleSettingsManager">
+ <option name="PER_PROJECT_SETTINGS">
+ <value>
+ <option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
+ <option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="1000" />
+ <option name="RIGHT_MARGIN" value="80" />
+ <option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
+ <option name="PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE" value="true" />
+ <ADDITIONAL_INDENT_OPTIONS fileType="java">
+ <option name="INDENT_SIZE" value="4" />
+ <option name="CONTINUATION_INDENT_SIZE" value="8" />
+ <option name="TAB_SIZE" value="4" />
+ <option name="USE_TAB_CHARACTER" value="false" />
+ <option name="SMART_TABS" value="false" />
+ <option name="LABEL_INDENT_SIZE" value="0" />
+ <option name="LABEL_INDENT_ABSOLUTE" value="false" />
+ </ADDITIONAL_INDENT_OPTIONS>
+ <ADDITIONAL_INDENT_OPTIONS fileType="xml">
+ <option name="INDENT_SIZE" value="4" />
+ <option name="CONTINUATION_INDENT_SIZE" value="8" />
+ <option name="TAB_SIZE" value="4" />
+ <option name="USE_TAB_CHARACTER" value="false" />
+ <option name="SMART_TABS" value="false" />
+ <option name="LABEL_INDENT_SIZE" value="0" />
+ <option name="LABEL_INDENT_ABSOLUTE" value="false" />
+ </ADDITIONAL_INDENT_OPTIONS>
+ </value>
+ </option>
+ <option name="USE_PER_PROJECT_SETTINGS" value="true" />
+ </component>
+ <component name="CompilerConfiguration">
+ <option name="DEFAULT_COMPILER" value="Javac" />
+ <option name="DEPLOY_AFTER_MAKE" value="0" />
+ <resourceExtensions>
+ <entry name=".+\.(properties|xml|html|dtd|tld)" />
+ <entry name=".+\.(gif|png|jpeg|jpg)" />
+ </resourceExtensions>
+ <wildcardResourcePatterns>
+ <entry name="?*.properties" />
+ <entry name="?*.xml" />
+ <entry name="?*.gif" />
+ <entry name="?*.png" />
+ <entry name="?*.jpeg" />
+ <entry name="?*.jpg" />
+ <entry name="?*.html" />
+ <entry name="?*.dtd" />
+ <entry name="?*.tld" />
+ </wildcardResourcePatterns>
+ </component>
+ <component name="DependenciesAnalyzeManager">
+ <option name="myForwardDirection" value="false" />
+ </component>
+ <component name="DependencyValidationManager">
+ <option name="SKIP_IMPORT_STATEMENTS" value="false" />
+ </component>
+ <component name="EclipseCompilerSettings">
+ <option name="DEBUGGING_INFO" value="true" />
+ <option name="GENERATE_NO_WARNINGS" value="true" />
+ <option name="DEPRECATION" value="false" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+ <option name="MAXIMUM_HEAP_SIZE" value="128" />
+ </component>
+ <component name="EclipseEmbeddedCompilerSettings">
+ <option name="DEBUGGING_INFO" value="true" />
+ <option name="GENERATE_NO_WARNINGS" value="true" />
+ <option name="DEPRECATION" value="false" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+ <option name="MAXIMUM_HEAP_SIZE" value="128" />
+ </component>
+ <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
+ <component name="EntryPointsManager">
+ <entry_points />
+ </component>
+ <component name="ExportToHTMLSettings">
+ <option name="PRINT_LINE_NUMBERS" value="false" />
+ <option name="OPEN_IN_BROWSER" value="false" />
+ <option name="OUTPUT_DIRECTORY" />
+ </component>
+ <component name="IdProvider" IDEtalkID="D171F99B9178C1675593DC9A76A5CC7E" />
+ <component name="InspectionProjectProfileManager">
+ <option name="PROJECT_PROFILE" value="Project Default" />
+ <option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
+ <scopes />
+ <profiles>
+ <profile version="1.0" is_locked="false">
+ <option name="myName" value="Project Default" />
+ <option name="myLocal" value="false" />
+ <inspection_tool class="JavaDoc" level="WARNING" enabled="false">
+ <option name="TOP_LEVEL_CLASS_OPTIONS">
+ <value>
+ <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+ <option name="REQUIRED_TAGS" value="" />
+ </value>
+ </option>
+ <option name="INNER_CLASS_OPTIONS">
+ <value>
+ <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+ <option name="REQUIRED_TAGS" value="" />
+ </value>
+ </option>
+ <option name="METHOD_OPTIONS">
+ <value>
+ <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+ <option name="REQUIRED_TAGS" value="@return@param@throws or @exception" />
+ </value>
+ </option>
+ <option name="FIELD_OPTIONS">
+ <value>
+ <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+ <option name="REQUIRED_TAGS" value="" />
+ </value>
+ </option>
+ <option name="IGNORE_DEPRECATED" value="false" />
+ <option name="IGNORE_JAVADOC_PERIOD" value="true" />
+ <option name="myAdditionalJavadocTags" value="" />
+ </inspection_tool>
+ </profile>
+ </profiles>
+ <list size="0" />
+ </component>
+ <component name="JavacSettings">
+ <option name="DEBUGGING_INFO" value="true" />
+ <option name="GENERATE_NO_WARNINGS" value="false" />
+ <option name="DEPRECATION" value="true" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+ <option name="MAXIMUM_HEAP_SIZE" value="128" />
+ </component>
+ <component name="JavadocGenerationManager">
+ <option name="OUTPUT_DIRECTORY" />
+ <option name="OPTION_SCOPE" value="protected" />
+ <option name="OPTION_HIERARCHY" value="true" />
+ <option name="OPTION_NAVIGATOR" value="true" />
+ <option name="OPTION_INDEX" value="true" />
+ <option name="OPTION_SEPARATE_INDEX" value="true" />
+ <option name="OPTION_DOCUMENT_TAG_USE" value="false" />
+ <option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" />
+ <option name="OPTION_DOCUMENT_TAG_VERSION" value="false" />
+ <option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" />
+ <option name="OPTION_DEPRECATED_LIST" value="true" />
+ <option name="OTHER_OPTIONS" value="" />
+ <option name="HEAP_SIZE" />
+ <option name="LOCALE" />
+ <option name="OPEN_IN_BROWSER" value="true" />
+ </component>
+ <component name="JikesSettings">
+ <option name="JIKES_PATH" value="" />
+ <option name="DEBUGGING_INFO" value="true" />
+ <option name="DEPRECATION" value="true" />
+ <option name="GENERATE_NO_WARNINGS" value="false" />
+ <option name="IS_EMACS_ERRORS_MODE" value="true" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+ </component>
+ <component name="LogConsolePreferences">
+ <option name="FILTER_ERRORS" value="false" />
+ <option name="FILTER_WARNINGS" value="false" />
+ <option name="FILTER_INFO" value="true" />
+ <option name="CUSTOM_FILTER" />
+ </component>
+ <component name="Palette2">
+ <group name="Swing">
+ <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
+ </item>
+ <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
+ </item>
+ <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
+ </item>
+ <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
+ <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
+ </item>
+ <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
+ <initial-values>
+ <property name="text" value="Button" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+ <initial-values>
+ <property name="text" value="RadioButton" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+ <initial-values>
+ <property name="text" value="CheckBox" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
+ <initial-values>
+ <property name="text" value="Label" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+ <preferred-size width="150" height="-1" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+ <preferred-size width="150" height="-1" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+ <preferred-size width="150" height="-1" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
+ </item>
+ <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+ <preferred-size width="200" height="200" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+ <preferred-size width="200" height="200" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+ </item>
+ <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+ </item>
+ <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
+ </item>
+ <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
+ </item>
+ <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
+ <preferred-size width="-1" height="20" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
+ </item>
+ <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
+ </item>
+ </group>
+ </component>
+ <component name="ProjectDetails">
+ <option name="projectName" value="idegen" />
+ </component>
+ <component name="ProjectFileVersion" converted="true" />
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/idegen.iml" filepath="$PROJECT_DIR$/idegen.iml" />
+ </modules>
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.5" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/classes" />
+ </component>
+ <component name="RmicSettings">
+ <option name="IS_EANABLED" value="false" />
+ <option name="DEBUGGING_INFO" value="true" />
+ <option name="GENERATE_NO_WARNINGS" value="false" />
+ <option name="GENERATE_IIOP_STUBS" value="false" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+ </component>
+ <component name="SvnBranchConfigurationManager">
+ <option name="myVersion" value="124" />
+ </component>
+ <component name="VcsDirectoryMappings">
+ <mapping directory="" vcs="Perforce" />
+ </component>
+ <component name="com.intellij.jsf.UserDefinedFacesConfigs">
+ <option name="USER_DEFINED_CONFIGS">
+ <value>
+ <list size="0" />
+ </value>
+ </option>
+ </component>
+ <component name="uidesigner-configuration">
+ <option name="INSTRUMENT_CLASSES" value="true" />
+ <option name="COPY_FORMS_RUNTIME_TO_OUTPUT" value="true" />
+ <option name="DEFAULT_LAYOUT_MANAGER" value="GridLayoutManager" />
+ </component>
+</project>
+
diff --git a/tools/idegen/idegen.sh b/tools/idegen/idegen.sh
new file mode 100755
index 0000000..d7e6986
--- /dev/null
+++ b/tools/idegen/idegen.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+if [ ! -d development ]; then
+ echo "Error: Run from the root of the tree."
+ exit 1
+fi
+
+idegenjar=`find out -name idegen.jar -follow | grep -v intermediates`
+if [ "" = "$idegenjar" ]; then
+ echo "Couldn't find idegen.jar. Please run make first."
+else
+ java -cp $idegenjar Main
+fi
diff --git a/tools/idegen/src/Configuration.java b/tools/idegen/src/Configuration.java
new file mode 100644
index 0000000..392cb5d
--- /dev/null
+++ b/tools/idegen/src/Configuration.java
@@ -0,0 +1,263 @@
+/*
+ * 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.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.SortedSet;
+import java.util.regex.Pattern;
+
+/**
+ * Immutable representation of an IDE configuration. Assumes that the current
+ * directory is the project's root directory.
+ */
+public class Configuration {
+
+ /** Java source tree roots. */
+ public final SortedSet<File> sourceRoots;
+
+ /** Found .jar files (that weren't excluded). */
+ public final List<File> jarFiles;
+
+ /** Excluded directories which may or may not be under a source root. */
+ public final SortedSet<File> excludedDirs;
+
+ /** The root directory for this tool. */
+ public final File toolDirectory;
+
+ /** File name used for excluded path files. */
+ private static final String EXCLUDED_PATHS = "excluded-paths";
+
+ /**
+ * Constructs a Configuration by traversing the directory tree, looking
+ * for .java and .jar files and identifying source roots.
+ */
+ public Configuration() throws IOException {
+ this.toolDirectory = new File("development/tools/idegen");
+ if (!toolDirectory.isDirectory()) {
+ // The wrapper script should have already verified this.
+ throw new AssertionError("Not in root directory.");
+ }
+
+ Stopwatch stopwatch = new Stopwatch();
+
+ Excludes excludes = readExcludes();
+
+ stopwatch.reset("Read excludes");
+
+ List<File> jarFiles = new ArrayList<File>(500);
+ SortedSet<File> excludedDirs = new TreeSet<File>();
+ SortedSet<File> sourceRoots = new TreeSet<File>();
+
+ traverse(new File("."), sourceRoots, jarFiles, excludedDirs, excludes);
+
+ stopwatch.reset("Traversed tree");
+
+ Log.debug(sourceRoots.size() + " source roots");
+ Log.debug(jarFiles.size() + " jar files");
+ Log.debug(excludedDirs.size() + " excluded dirs");
+
+ this.sourceRoots = Collections.unmodifiableSortedSet(sourceRoots);
+ this.jarFiles = Collections.unmodifiableList(jarFiles);
+ this.excludedDirs = Collections.unmodifiableSortedSet(excludedDirs);
+ }
+
+ /**
+ * Reads excluded path files.
+ */
+ private Excludes readExcludes() throws IOException {
+ List<Pattern> patterns = new ArrayList<Pattern>();
+
+ File globalExcludes = new File(toolDirectory, EXCLUDED_PATHS);
+ parseFile(globalExcludes, patterns);
+
+ // Look for Google-specific excludes.
+ // TODO: Traverse all vendor-specific directories.
+ File googleExcludes = new File("./vendor/google/" + EXCLUDED_PATHS);
+ if (googleExcludes.exists()) {
+ parseFile(googleExcludes, patterns);
+ }
+
+ // Look for user-specific excluded-paths file in current directory.
+ File localExcludes = new File(EXCLUDED_PATHS);
+ if (localExcludes.exists()) {
+ parseFile(localExcludes, patterns);
+ }
+
+ return new Excludes(patterns);
+ }
+
+ /**
+ * Recursively finds .java source roots, .jar files, and excluded
+ * directories.
+ */
+ private static void traverse(File directory, Set<File> sourceRoots,
+ Collection<File> jarFiles, Collection<File> excludedDirs,
+ Excludes excludes) throws IOException {
+ /*
+ * Note it would be faster to stop traversing a source root as soon as
+ * we encounter the first .java file, but it appears we have nested
+ * source roots in our generated source directory (specifically,
+ * R.java files and aidl .java files don't share the same source
+ * root).
+ */
+
+ boolean firstJavaFile = true;
+ for (File file : directory.listFiles()) {
+ // Trim preceding "./" from path.
+ String path = file.getPath().substring(2);
+
+ // Keep track of source roots for .java files.
+ if (path.endsWith(".java")) {
+ if (firstJavaFile) {
+ // Only parse one .java file per directory.
+ firstJavaFile = false;
+
+ File sourceRoot = rootOf(file);
+ if (sourceRoot != null) {
+ sourceRoots.add(sourceRoot);
+ }
+ }
+
+ continue;
+ }
+
+ // Keep track of .jar files.
+ if (path.endsWith(".jar")) {
+ if (!excludes.exclude(path)) {
+ jarFiles.add(file);
+ } else {
+ Log.debug("Skipped: " + file);
+ }
+
+ continue;
+ }
+
+ // Traverse nested directories.
+ if (file.isDirectory()) {
+ if (excludes.exclude(path)) {
+ // Don't recurse into excluded dirs.
+ Log.debug("Excluding: " + path);
+ excludedDirs.add(file);
+ } else {
+ traverse(file, sourceRoots, jarFiles, excludedDirs,
+ excludes);
+ }
+ }
+ }
+ }
+
+ /**
+ * Determines the source root for a given .java file. Returns null
+ * if the file doesn't have a package or if the file isn't in the
+ * correct directory structure.
+ */
+ private static File rootOf(File javaFile) throws IOException {
+ String packageName = parsePackageName(javaFile);
+ if (packageName == null) {
+ // No package.
+ // TODO: Treat this as a source root?
+ return null;
+ }
+
+ String packagePath = packageName.replace('.', File.separatorChar);
+ File parent = javaFile.getParentFile();
+ String parentPath = parent.getPath();
+ if (!parentPath.endsWith(packagePath)) {
+ // Bad dir structure.
+ return null;
+ }
+
+ return new File(parentPath.substring(
+ 0, parentPath.length() - packagePath.length()));
+ }
+
+ /**
+ * Reads a Java file and parses out the package name. Returns null if none
+ * found.
+ */
+ private static String parsePackageName(File file) throws IOException {
+ BufferedReader in = new BufferedReader(new FileReader(file));
+ try {
+ String line;
+ while ((line = in.readLine()) != null) {
+ String trimmed = line.trim();
+ if (trimmed.startsWith("package")) {
+ // TODO: Make this more robust.
+ // Assumes there's only once space after "package" and the
+ // line ends in a ";".
+ return trimmed.substring(8, trimmed.length() - 1);
+ }
+ }
+
+ return null;
+ } finally {
+ in.close();
+ }
+ }
+
+ /**
+ * Picks out excluded directories that are under source roots.
+ */
+ public SortedSet<File> excludesUnderSourceRoots() {
+ // TODO: Refactor this to share the similar logic in
+ // Eclipse.constructExcluding().
+ SortedSet<File> picked = new TreeSet<File>();
+ for (File sourceRoot : sourceRoots) {
+ String sourcePath = sourceRoot.getPath() + "/";
+ SortedSet<File> tailSet = excludedDirs.tailSet(sourceRoot);
+ for (File file : tailSet) {
+ if (file.getPath().startsWith(sourcePath)) {
+ picked.add(file);
+ } else {
+ break;
+ }
+ }
+ }
+ return picked;
+ }
+
+ /**
+ * Reads a list of regular expressions from a file, one per line, and adds
+ * the compiled patterns to the given collection. Ignores lines starting
+ * with '#'.
+ *
+ * @param file containing regular expressions, one per line
+ * @param patterns collection to add compiled patterns from file to
+ */
+ public static void parseFile(File file, Collection<Pattern> patterns)
+ throws IOException {
+ BufferedReader in = new BufferedReader(new FileReader(file));
+ try {
+ String line;
+ while ((line = in.readLine()) != null) {
+ String trimmed = line.trim();
+ if (trimmed.length() > 0 && !trimmed.startsWith("#")) {
+ patterns.add(Pattern.compile(trimmed));
+ }
+ }
+ } finally {
+ in.close();
+ }
+ }
+}
diff --git a/tools/idegen/src/Eclipse.java b/tools/idegen/src/Eclipse.java
new file mode 100644
index 0000000..403c7d8
--- /dev/null
+++ b/tools/idegen/src/Eclipse.java
@@ -0,0 +1,188 @@
+/*
+ * 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.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.Collection;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * Generates an Eclipse project.
+ */
+public class Eclipse {
+
+ /**
+ * Generates an Eclipse .classpath file from the given configuration.
+ */
+ public static void generateFrom(Configuration c) throws IOException {
+ StringBuilder classpath = new StringBuilder();
+
+ classpath.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ + "<classpath>\n");
+
+ /*
+ * If the user has a file named "path-precedence" in their project's
+ * root directory, we'll order source roots based on how they match
+ * regular expressions in that file. Source roots that match earlier
+ * patterns will come sooner in configuration file.
+ */
+ List<Pattern> patterns = new ArrayList<Pattern>();
+
+ File precedence = new File("path-precedence");
+ if (precedence.exists()) {
+ Configuration.parseFile(precedence, patterns);
+ } else {
+ // Put ./out at the bottom by default.
+ patterns.add(Pattern.compile("^(?!out/)"));
+ }
+
+ // Everything not matched by the user's precedence spec.
+ patterns.add(Pattern.compile(".*"));
+
+
+ List<Bucket> buckets = new ArrayList<Bucket>(patterns.size());
+ for (Pattern pattern : patterns) {
+ buckets.add(new Bucket(pattern));
+ }
+
+ // Put source roots in respective buckets.
+ OUTER: for (File sourceRoot : c.sourceRoots) {
+ // Trim preceding "./" from path.
+ String path = sourceRoot.getPath().substring(2);
+
+ for (Bucket bucket : buckets) {
+ if (bucket.matches(path)) {
+ bucket.sourceRoots.add(sourceRoot);
+ continue OUTER;
+ }
+ }
+ }
+
+ // Output source roots to configuration file.
+ for (Bucket bucket : buckets) {
+ for (File sourceRoot : bucket.sourceRoots) {
+ classpath.append(" <classpathentry kind=\"src\"");
+ CharSequence excluding = constructExcluding(sourceRoot, c);
+ if (excluding.length() > 0) {
+ classpath.append(" excluding=\"")
+ .append(excluding).append("\"");
+ }
+ classpath.append(" path=\"")
+ .append(trimmed(sourceRoot)).append("\"/>\n");
+ }
+
+ }
+
+ // Output .jar entries.
+ for (File jar : c.jarFiles) {
+ classpath.append(" <classpathentry kind=\"lib\" path=\"")
+ .append(trimmed(jar)).append("\"/>\n");
+ }
+
+ /*
+ * Output directory. Unfortunately, Eclipse forces us to put it
+ * somewhere under the project directory.
+ */
+ classpath.append(" <classpathentry kind=\"output\" path=\""
+ + "out/eclipse\"/>\n");
+
+ classpath.append("</classpath>\n");
+
+ Files.toFile(classpath.toString(), new File(".classpath"));
+ }
+
+
+ /**
+ * Constructs the "excluding" argument for a given source root.
+ */
+ private static CharSequence constructExcluding(File sourceRoot,
+ Configuration c) {
+ StringBuilder classpath = new StringBuilder();
+ String path = sourceRoot.getPath();
+
+ // Exclude nested source roots.
+ SortedSet<File> nextRoots = c.sourceRoots.tailSet(sourceRoot);
+ int count = 0;
+ for (File nextRoot : nextRoots) {
+ // The first root is this root.
+ if (count == 0) {
+ count++;
+ continue;
+ }
+
+ String nextPath = nextRoot.getPath();
+ if (!nextPath.startsWith(path)) {
+ break;
+ }
+
+ if (count > 1) {
+ classpath.append('|');
+ }
+ classpath.append(nextPath.substring(path.length() + 1))
+ .append('/');
+
+ count++;
+ }
+
+ // Exclude excluded directories under this source root.
+ SortedSet<File> excludedDirs = c.excludedDirs.tailSet(sourceRoot);
+ for (File excludedDir : excludedDirs) {
+ String excludedPath = excludedDir.getPath();
+ if (!excludedPath.startsWith(path)) {
+ break;
+ }
+
+ if (count > 1) {
+ classpath.append('|');
+ }
+ classpath.append(excludedPath.substring(path.length() + 1))
+ .append('/');
+
+ count++;
+ }
+
+ return classpath;
+ }
+
+ /**
+ * Returns the trimmed path.
+ */
+ private static String trimmed(File file) {
+ return file.getPath().substring(2);
+ }
+
+ /**
+ * A precedence bucket for source roots.
+ */
+ private static class Bucket {
+
+ private final Pattern pattern;
+ private final List<File> sourceRoots = new ArrayList<File>();
+
+ private Bucket(Pattern pattern) {
+ this.pattern = pattern;
+ }
+
+ private boolean matches(String path) {
+ return pattern.matcher(path).find();
+ }
+ }
+}
diff --git a/tools/idegen/src/Excludes.java b/tools/idegen/src/Excludes.java
new file mode 100644
index 0000000..8531d47
--- /dev/null
+++ b/tools/idegen/src/Excludes.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+import java.util.regex.Pattern;
+import java.util.List;
+
+/**
+ * Decides whether or not to exclude certain paths.
+ */
+public class Excludes {
+
+ private final List<Pattern> patterns;
+
+ /**
+ * Constructs a set of excludes matching the given patterns.
+ */
+ public Excludes(List<Pattern> patterns) {
+ this.patterns = patterns;
+ }
+
+ /**
+ * Returns true if the given path should be excluded.
+ */
+ public boolean exclude(String path) {
+ for (Pattern pattern : patterns) {
+ if (pattern.matcher(path).find()) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/tools/idegen/src/Files.java b/tools/idegen/src/Files.java
new file mode 100644
index 0000000..81176ee
--- /dev/null
+++ b/tools/idegen/src/Files.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+
+import java.io.*;
+
+/**
+ * File utility methods.
+ */
+class Files {
+
+ /**
+ * Reads file into a string using default encoding.
+ */
+ static String toString(File file) throws IOException {
+ char[] buffer = new char[0x1000]; // 4k
+ int read;
+ Reader in = new FileReader(file);
+ StringBuilder builder = new StringBuilder();
+ while ((read = in.read(buffer)) > -1) {
+ builder.append(buffer, 0, read);
+ }
+ in.close();
+ return builder.toString();
+ }
+
+ /**
+ * Writes a string to a file using default encoding.
+ */
+ static void toFile(String contents, File file) throws IOException {
+ FileWriter out = new FileWriter(file);
+ out.write(contents);
+ out.close();
+ }
+}
\ No newline at end of file
diff --git a/tools/idegen/src/IntelliJ.java b/tools/idegen/src/IntelliJ.java
new file mode 100644
index 0000000..00d731d
--- /dev/null
+++ b/tools/idegen/src/IntelliJ.java
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.util.SortedSet;
+
+/**
+ * Generates an IntelliJ project.
+ */
+public class IntelliJ {
+
+ private static final String IDEA_IML = "android.iml";
+ private static final String IDEA_IPR = "android.ipr";
+
+ /**
+ * Generates IntelliJ configuration files from the given configuration.
+ */
+ public static void generateFrom(Configuration c) throws IOException {
+ File templatesDirectory = new File(c.toolDirectory, "templates");
+ String ipr = Files.toString(new File(templatesDirectory, IDEA_IPR));
+ Files.toFile(ipr, new File(IDEA_IPR));
+
+ String iml = Files.toString(new File(templatesDirectory, IDEA_IML));
+
+ StringBuilder sourceRootsXml = new StringBuilder();
+ for (File sourceRoot : c.sourceRoots) {
+ sourceRootsXml.append("<sourceFolder url=\"file://$MODULE_DIR$/")
+ .append(sourceRoot.getPath())
+ .append("\" isTestSource=\"").append(isTests(sourceRoot))
+ .append("\"/>\n");
+ }
+
+ /*
+ * IntelliJ excludes are module-wide. We explicitly exclude directories
+ * under source roots but leave the rest in so you can still pull
+ * up random non-Java files.
+ */
+ StringBuilder excludeXml = new StringBuilder();
+ for (File excludedDir : c.excludesUnderSourceRoots()) {
+ sourceRootsXml.append("<excludeFolder url=\"file://$MODULE_DIR$/")
+ .append(excludedDir.getPath())
+ .append("\"/>\n");
+ }
+
+ // Exclude Eclipse's output directory.
+ sourceRootsXml.append("<excludeFolder "
+ + "url=\"file://$MODULE_DIR$/out/eclipse\"/>\n");
+
+ StringBuilder jarsXml = new StringBuilder();
+ for (File jar : c.jarFiles) {
+ jarsXml.append("<orderEntry type=\"module-library\">"
+ + "<library><CLASSES><root url=\"jar://$MODULE_DIR$/")
+ .append(jar.getPath())
+ .append("!/\"/></CLASSES><JAVADOC/><SOURCES/></library>"
+ + "</orderEntry>\n");
+ }
+
+ iml = iml.replace("SOURCE_FOLDERS",
+ sourceRootsXml.toString() + excludeXml.toString());
+ iml = iml.replace("JAR_ENTRIES", jarsXml.toString());
+
+ Files.toFile(iml, new File(IDEA_IML));
+ }
+
+ private static boolean isTests(File file) {
+ String path = file.getPath();
+
+ // test-runner is testing infrastructure, not test code.
+ if (path.contains("test-runner")) {
+ return false;
+ }
+
+ return path.toUpperCase().contains("TEST");
+ }
+}
\ No newline at end of file
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java b/tools/idegen/src/Log.java
similarity index 61%
copy from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java
copy to tools/idegen/src/Log.java
index 4c368d9..e35d060 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java
+++ b/tools/idegen/src/Log.java
@@ -14,19 +14,20 @@
* limitations under the License.
*/
-
-package com.android.ide.eclipse.editors.uimodel;
-
/**
- * This interface decoration indicates that a given UiAttributeNode can both
- * set and get its current value.
+ * Logs messages.
*/
-public interface IUiSettableAttributeNode {
+class Log {
- /** Returns the current value of the node. */
- public String getCurrentValue();
-
- /** Sets the current value of the node. */
- public void setCurrentValue(String value);
+ static final boolean DEBUG = false;
+ static void debug(String message) {
+ if (DEBUG) {
+ info(message);
+ }
+ }
+
+ static void info(String message) {
+ System.out.println(message);
+ }
}
diff --git a/tools/idegen/src/Main.java b/tools/idegen/src/Main.java
new file mode 100644
index 0000000..294dbee
--- /dev/null
+++ b/tools/idegen/src/Main.java
@@ -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.
+ */
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * Generates IntelliJ and Eclipse project configurations.
+ */
+public class Main {
+
+ public static void main(String[] args) throws Exception {
+ Configuration configuration = new Configuration();
+ IntelliJ.generateFrom(configuration);
+ Eclipse.generateFrom(configuration);
+ }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java b/tools/idegen/src/Stopwatch.java
similarity index 61%
copy from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java
copy to tools/idegen/src/Stopwatch.java
index 4c368d9..4bd2ae8 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java
+++ b/tools/idegen/src/Stopwatch.java
@@ -14,19 +14,16 @@
* limitations under the License.
*/
-
-package com.android.ide.eclipse.editors.uimodel;
-
/**
- * This interface decoration indicates that a given UiAttributeNode can both
- * set and get its current value.
+ * Measures passed time.
*/
-public interface IUiSettableAttributeNode {
+class Stopwatch {
- /** Returns the current value of the node. */
- public String getCurrentValue();
-
- /** Sets the current value of the node. */
- public void setCurrentValue(String value);
+ long last = System.currentTimeMillis();
-}
+ void reset(String label) {
+ long now = System.currentTimeMillis();
+ Log.info(label + ": " + (now - last) + "ms");
+ last = now;
+ }
+}
\ No newline at end of file
diff --git a/tools/idegen/templates/android.iml b/tools/idegen/templates/android.iml
new file mode 100644
index 0000000..12e934c
--- /dev/null
+++ b/tools/idegen/templates/android.iml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="JAVA_MODULE">
+ <component name="ModuleRootManager" />
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ SOURCE_FOLDERS
+ </content>
+ JAR_ENTRIES
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="inheritedJdk" />
+ <orderEntryProperties />
+ </component>
+</module>
+
diff --git a/tools/idegen/templates/android.ipr b/tools/idegen/templates/android.ipr
new file mode 100644
index 0000000..d6aba4b
--- /dev/null
+++ b/tools/idegen/templates/android.ipr
@@ -0,0 +1,311 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project relativePaths="true" version="4">
+ <component name="AntConfiguration">
+ <defaultAnt bundledAnt="true" />
+ <buildFile url="file://$PROJECT_DIR$/ide/intellij/build.xml">
+ <additionalClassPath />
+ <antReference projectDefault="true" />
+ <customJdkName value="" />
+ <maximumHeapSize value="128" />
+ <properties />
+ </buildFile>
+ </component>
+ <component name="BuildJarProjectSettings">
+ <option name="BUILD_JARS_ON_MAKE" value="false" />
+ </component>
+ <component name="CodeStyleProjectProfileManger">
+ <option name="PROJECT_PROFILE" />
+ <option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
+ </component>
+ <component name="CodeStyleSettingsManager">
+ <option name="PER_PROJECT_SETTINGS">
+ <value>
+ <option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
+ <option name="RIGHT_MARGIN" value="80" />
+ <option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
+ <option name="PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE" value="true" />
+ </value>
+ </option>
+ <option name="USE_PER_PROJECT_SETTINGS" value="true" />
+ </component>
+ <component name="CompilerConfiguration">
+ <option name="DEFAULT_COMPILER" value="Javac" />
+ <option name="DEPLOY_AFTER_MAKE" value="0" />
+ <resourceExtensions>
+ <entry name=".+\.(properties|xml|html|dtd|tld)" />
+ <entry name=".+\.(gif|png|jpeg|jpg)" />
+ </resourceExtensions>
+ <wildcardResourcePatterns>
+ <entry name="?*.properties" />
+ <entry name="?*.xml" />
+ <entry name="?*.gif" />
+ <entry name="?*.png" />
+ <entry name="?*.jpeg" />
+ <entry name="?*.jpg" />
+ <entry name="?*.html" />
+ <entry name="?*.dtd" />
+ <entry name="?*.tld" />
+ </wildcardResourcePatterns>
+ </component>
+ <component name="DependenciesAnalyzeManager">
+ <option name="myForwardDirection" value="false" />
+ </component>
+ <component name="DependencyValidationManager">
+ <option name="SKIP_IMPORT_STATEMENTS" value="false" />
+ </component>
+ <component name="EclipseCompilerSettings">
+ <option name="DEBUGGING_INFO" value="true" />
+ <option name="GENERATE_NO_WARNINGS" value="true" />
+ <option name="DEPRECATION" value="false" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+ <option name="MAXIMUM_HEAP_SIZE" value="128" />
+ </component>
+ <component name="EclipseEmbeddedCompilerSettings">
+ <option name="DEBUGGING_INFO" value="true" />
+ <option name="GENERATE_NO_WARNINGS" value="true" />
+ <option name="DEPRECATION" value="false" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+ <option name="MAXIMUM_HEAP_SIZE" value="128" />
+ </component>
+ <component name="EntryPointsManager">
+ <entry_points version="2.0" />
+ </component>
+ <component name="ExportToHTMLSettings">
+ <option name="PRINT_LINE_NUMBERS" value="false" />
+ <option name="OPEN_IN_BROWSER" value="false" />
+ <option name="OUTPUT_DIRECTORY" />
+ </component>
+ <component name="IdProvider" IDEtalkID="C8FEF8FDDA8778BFC0BDE2CF5A21CB2C" />
+ <component name="InspectionProjectProfileManager">
+ <option name="PROJECT_PROFILE" value="Project Default" />
+ <option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
+ <scopes />
+ <profiles>
+ <profile version="1.0" is_locked="false">
+ <option name="myName" value="Project Default" />
+ <option name="myLocal" value="false" />
+ <inspection_tool class="JavaDoc" level="WARNING" enabled="false">
+ <option name="TOP_LEVEL_CLASS_OPTIONS">
+ <value>
+ <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+ <option name="REQUIRED_TAGS" value="" />
+ </value>
+ </option>
+ <option name="INNER_CLASS_OPTIONS">
+ <value>
+ <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+ <option name="REQUIRED_TAGS" value="" />
+ </value>
+ </option>
+ <option name="METHOD_OPTIONS">
+ <value>
+ <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+ <option name="REQUIRED_TAGS" value="@return@param@throws or @exception" />
+ </value>
+ </option>
+ <option name="FIELD_OPTIONS">
+ <value>
+ <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+ <option name="REQUIRED_TAGS" value="" />
+ </value>
+ </option>
+ <option name="IGNORE_DEPRECATED" value="false" />
+ <option name="IGNORE_JAVADOC_PERIOD" value="true" />
+ <option name="myAdditionalJavadocTags" value="" />
+ </inspection_tool>
+ </profile>
+ </profiles>
+ <list size="0" />
+ </component>
+ <component name="JavacSettings">
+ <option name="DEBUGGING_INFO" value="true" />
+ <option name="GENERATE_NO_WARNINGS" value="false" />
+ <option name="DEPRECATION" value="false" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="-Xlint:all,-deprecation,-serial" />
+ <option name="MAXIMUM_HEAP_SIZE" value="512" />
+ </component>
+ <component name="JavadocGenerationManager">
+ <option name="OUTPUT_DIRECTORY" />
+ <option name="OPTION_SCOPE" value="protected" />
+ <option name="OPTION_HIERARCHY" value="true" />
+ <option name="OPTION_NAVIGATOR" value="true" />
+ <option name="OPTION_INDEX" value="true" />
+ <option name="OPTION_SEPARATE_INDEX" value="true" />
+ <option name="OPTION_DOCUMENT_TAG_USE" value="false" />
+ <option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" />
+ <option name="OPTION_DOCUMENT_TAG_VERSION" value="false" />
+ <option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" />
+ <option name="OPTION_DEPRECATED_LIST" value="true" />
+ <option name="OTHER_OPTIONS" value="" />
+ <option name="HEAP_SIZE" />
+ <option name="LOCALE" />
+ <option name="OPEN_IN_BROWSER" value="true" />
+ </component>
+ <component name="JikesSettings">
+ <option name="JIKES_PATH" value="" />
+ <option name="DEBUGGING_INFO" value="true" />
+ <option name="DEPRECATION" value="true" />
+ <option name="GENERATE_NO_WARNINGS" value="false" />
+ <option name="IS_EMACS_ERRORS_MODE" value="true" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+ </component>
+ <component name="LogConsolePreferences">
+ <option name="FILTER_ERRORS" value="false" />
+ <option name="FILTER_WARNINGS" value="false" />
+ <option name="FILTER_INFO" value="true" />
+ <option name="CUSTOM_FILTER" />
+ </component>
+ <component name="Palette2">
+ <group name="Swing">
+ <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
+ </item>
+ <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
+ </item>
+ <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
+ </item>
+ <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
+ <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
+ </item>
+ <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
+ <initial-values>
+ <property name="text" value="Button" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+ <initial-values>
+ <property name="text" value="RadioButton" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+ <initial-values>
+ <property name="text" value="CheckBox" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
+ <initial-values>
+ <property name="text" value="Label" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+ <preferred-size width="150" height="-1" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+ <preferred-size width="150" height="-1" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+ <preferred-size width="150" height="-1" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
+ </item>
+ <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+ <preferred-size width="200" height="200" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+ <preferred-size width="200" height="200" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+ </item>
+ <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+ </item>
+ <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
+ </item>
+ <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
+ </item>
+ <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
+ <preferred-size width="-1" height="20" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
+ </item>
+ <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
+ </item>
+ </group>
+ </component>
+ <component name="ProjectFileVersion" converted="true" />
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/android.iml" filepath="$PROJECT_DIR$/android.iml" />
+ </modules>
+ </component>
+ <component name="ProjectRootManager" version="2" assert-keyword="true" jdk-15="true" project-jdk-name="1.5 (No Libraries)" project-jdk-type="JavaSDK">
+ <output url="file:///tmp/intellij$PROJECT_DIR$/classes" />
+ </component>
+ <component name="RmicSettings">
+ <option name="IS_EANABLED" value="false" />
+ <option name="DEBUGGING_INFO" value="true" />
+ <option name="GENERATE_NO_WARNINGS" value="false" />
+ <option name="GENERATE_IIOP_STUBS" value="false" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+ </component>
+ <component name="VcsDirectoryMappings">
+ <mapping directory="" vcs="Perforce" />
+ </component>
+ <component name="com.intellij.jsf.UserDefinedFacesConfigs">
+ <option name="USER_DEFINED_CONFIGS">
+ <value>
+ <list size="0" />
+ </value>
+ </option>
+ </component>
+ <component name="uidesigner-configuration">
+ <option name="INSTRUMENT_CLASSES" value="true" />
+ <option name="COPY_FORMS_RUNTIME_TO_OUTPUT" value="true" />
+ <option name="DEFAULT_LAYOUT_MANAGER" value="GridLayoutManager" />
+ </component>
+</project>
+
diff --git a/tools/jarutils/src/com/android/jarutils/DebugKeyProvider.java b/tools/jarutils/src/com/android/jarutils/DebugKeyProvider.java
index 966f0b4..6dc32ba 100644
--- a/tools/jarutils/src/com/android/jarutils/DebugKeyProvider.java
+++ b/tools/jarutils/src/com/android/jarutils/DebugKeyProvider.java
@@ -19,12 +19,9 @@
import com.android.prefs.AndroidLocation;
import com.android.prefs.AndroidLocation.AndroidLocationException;
-import java.io.BufferedReader;
-import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
-import java.io.InputStreamReader;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
@@ -33,7 +30,6 @@
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
-import java.util.ArrayList;
/**
* A provider of a dummy key to sign Android application for debugging purpose.
@@ -88,46 +84,29 @@
* <p/>The keystore, and a new random android debug key are created if they do not yet exist.
* <p/>Password for the store/key is <code>android</code>, and the key alias is
* <code>AndroidDebugKey</code>.
- * @param osKeyStorePath the OS path to the keystore.
+ * @param osKeyStorePath the OS path to the keystore, or <code>null</code> if the default one
+ * is to be used.
* @param storeType an optional keystore type, or <code>null</code> if the default is to
* be used.
* @param output an optional {@link IKeyGenOutput} object to get the stdout and stderr
* of the keytool process call.
* @throws KeytoolException If the creation of the debug key failed.
+ * @throws AndroidLocationException
*/
public DebugKeyProvider(String osKeyStorePath, String storeType, IKeyGenOutput output)
throws KeyStoreException, NoSuchAlgorithmException, CertificateException,
- UnrecoverableEntryException, IOException, KeytoolException {
+ UnrecoverableEntryException, IOException, KeytoolException, AndroidLocationException {
- if (loadKeyEntry(osKeyStorePath, storeType) == false) {
- // create the store with they key
- createNewStore(osKeyStorePath, storeType, output);
+ if (osKeyStorePath == null) {
+ osKeyStorePath = getDefaultKeyStoreOsPath();
}
- }
-
- /**
- * Creates a provider using the default keystore location.
- * <p/>The keystore, and a new random android debug key are created if they do not yet exist.
- * <p/>Password for the store/key is <code>android</code>, and the key alias is
- * <code>AndroidDebugKey</code>.
- * @param storeType an optional keystore type, or <code>null</code> if the default is to
- * be used.
- * @param output an optional {@link IKeyGenOutput} object to get the stdout and stderr
- * of the keytool process call.
- * @throws KeytoolException If the creation of the debug key failed.
- * @throws AndroidLocationException If getting the location to store android files failed.
- */
- public DebugKeyProvider(String storeType, IKeyGenOutput output) throws KeyStoreException,
- NoSuchAlgorithmException, CertificateException, UnrecoverableEntryException,
- IOException, KeytoolException, AndroidLocationException {
-
- String osKeyStorePath = getDefaultKeyStoreOsPath();
+
if (loadKeyEntry(osKeyStorePath, storeType) == false) {
// create the store with the key
createNewStore(osKeyStorePath, storeType, output);
}
}
-
+
/**
* Returns the OS path to the default debug keystore.
*
@@ -215,168 +194,9 @@
throws KeyStoreException, NoSuchAlgorithmException, CertificateException,
UnrecoverableEntryException, IOException, KeytoolException {
- // get the executable name of keytool depending on the platform.
- String os = System.getProperty("os.name");
-
- String keytoolCommand;
- if (os.startsWith("Windows")) {
- keytoolCommand = "keytool.exe";
- } else {
- keytoolCommand = "keytool";
- }
-
- String javaHome = System.getProperty("java.home");
-
- if (javaHome != null && javaHome.length() > 0) {
- keytoolCommand = javaHome + File.separator + "bin" + File.separator + keytoolCommand;
- }
-
- // create the command line to call key tool to build the key with no user input.
- ArrayList<String> commandList = new ArrayList<String>();
- commandList.add(keytoolCommand);
- commandList.add("-genkey");
- commandList.add("-alias");
- commandList.add(DEBUG_ALIAS);
- commandList.add("-keyalg");
- commandList.add("RSA");
- commandList.add("-dname");
- commandList.add(CERTIFICATE_DESC);
- commandList.add("-validity");
- commandList.add("365");
- commandList.add("-keypass");
- commandList.add(PASSWORD_STRING);
- commandList.add("-keystore");
- commandList.add(osKeyStorePath);
- commandList.add("-storepass");
- commandList.add(PASSWORD_STRING);
- if (storeType != null) {
- commandList.add("-storetype");
- commandList.add(storeType);
- }
-
- String[] commandArray = commandList.toArray(new String[commandList.size()]);
-
- // launch the command line process
- int result = 0;
- try {
- result = grabProcessOutput(Runtime.getRuntime().exec(commandArray), output);
- } catch (Exception e) {
- // create the command line as one string
- StringBuilder builder = new StringBuilder();
- boolean firstArg = true;
- for (String arg : commandArray) {
- boolean hasSpace = arg.indexOf(' ') != -1;
-
- if (firstArg == true) {
- firstArg = false;
- } else {
- builder.append(' ');
- }
-
- if (hasSpace) {
- builder.append('"');
- }
-
- builder.append(arg);
-
- if (hasSpace) {
- builder.append('"');
- }
- }
-
- throw new KeytoolException("Failed to create debug key: " + e.getMessage(),
- javaHome, builder.toString());
- }
-
- if (result != 0) {
- return;
- }
- loadKeyEntry(osKeyStorePath, storeType);
- }
-
- /**
- * Get the stderr/stdout outputs of a process and return when the process is done.
- * Both <b>must</b> be read or the process will block on windows.
- * @param process The process to get the ouput from
- * @return the process return code.
- * @throws InterruptedException
- */
- private int grabProcessOutput(final Process process, final IKeyGenOutput output) {
- // read the lines as they come. if null is returned, it's
- // because the process finished
- Thread t1 = new Thread("") {
- @Override
- public void run() {
- // create a buffer to read the stderr output
- InputStreamReader is = new InputStreamReader(process.getErrorStream());
- BufferedReader errReader = new BufferedReader(is);
-
- try {
- while (true) {
- String line = errReader.readLine();
- if (line != null) {
- if (output != null) {
- output.err(line);
- } else {
- System.err.println(line);
- }
- } else {
- break;
- }
- }
- } catch (IOException e) {
- // do nothing.
- }
- }
- };
-
- Thread t2 = new Thread("") {
- @Override
- public void run() {
- InputStreamReader is = new InputStreamReader(process.getInputStream());
- BufferedReader outReader = new BufferedReader(is);
-
- try {
- while (true) {
- String line = outReader.readLine();
- if (line != null) {
- if (output != null) {
- output.out(line);
- } else {
- System.out.println(line);
- }
- } else {
- break;
- }
- }
- } catch (IOException e) {
- // do nothing.
- }
- }
- };
-
- t1.start();
- t2.start();
-
- // it looks like on windows process#waitFor() can return
- // before the thread have filled the arrays, so we wait for both threads and the
- // process itself.
- try {
- t1.join();
- } catch (InterruptedException e) {
- }
- try {
- t2.join();
- } catch (InterruptedException e) {
- }
-
- // get the return code from the process
- try {
- return process.waitFor();
- } catch (InterruptedException e) {
- // since we're waiting for the output thread above, we should never actually wait
- // on the process to end, since it'll be done by the time we call waitFor()
- return 0;
+ if (KeystoreHelper.createNewStore(osKeyStorePath, storeType, PASSWORD_STRING, DEBUG_ALIAS,
+ PASSWORD_STRING, CERTIFICATE_DESC, 1 /* validity*/, output)) {
+ loadKeyEntry(osKeyStorePath, storeType);
}
}
}
diff --git a/tools/jarutils/src/com/android/jarutils/JavaResourceFilter.java b/tools/jarutils/src/com/android/jarutils/JavaResourceFilter.java
index ca3dcc7..d9f8da6 100644
--- a/tools/jarutils/src/com/android/jarutils/JavaResourceFilter.java
+++ b/tools/jarutils/src/com/android/jarutils/JavaResourceFilter.java
@@ -90,6 +90,7 @@
"package.html".equalsIgnoreCase(fileName) == false &&
"overview.html".equalsIgnoreCase(fileName) == false &&
".cvsignore".equalsIgnoreCase(fileName) == false &&
- ".DS_Store".equals(fileName) == false;
+ ".DS_Store".equals(fileName) == false &&
+ fileName.charAt(fileName.length()-1) != '~';
}
}
diff --git a/tools/jarutils/src/com/android/jarutils/KeystoreHelper.java b/tools/jarutils/src/com/android/jarutils/KeystoreHelper.java
new file mode 100644
index 0000000..c694684
--- /dev/null
+++ b/tools/jarutils/src/com/android/jarutils/KeystoreHelper.java
@@ -0,0 +1,228 @@
+/*
+ * 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.jarutils;
+
+import com.android.jarutils.DebugKeyProvider.IKeyGenOutput;
+import com.android.jarutils.DebugKeyProvider.KeytoolException;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableEntryException;
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+
+/**
+ * A Helper to create new keystore/key.
+ */
+public final class KeystoreHelper {
+
+ /**
+ * Creates a new store
+ * @param osKeyStorePath the location of the store
+ * @param storeType an optional keystore type, or <code>null</code> if the default is to
+ * be used.
+ * @param output an optional {@link IKeyGenOutput} object to get the stdout and stderr
+ * of the keytool process call.
+ * @throws KeyStoreException
+ * @throws NoSuchAlgorithmException
+ * @throws CertificateException
+ * @throws UnrecoverableEntryException
+ * @throws IOException
+ * @throws KeytoolException
+ */
+ public static boolean createNewStore(
+ String osKeyStorePath,
+ String storeType,
+ String storePassword,
+ String alias,
+ String keyPassword,
+ String description,
+ int validityYears,
+ IKeyGenOutput output)
+ throws KeyStoreException, NoSuchAlgorithmException, CertificateException,
+ UnrecoverableEntryException, IOException, KeytoolException {
+
+ // get the executable name of keytool depending on the platform.
+ String os = System.getProperty("os.name");
+
+ String keytoolCommand;
+ if (os.startsWith("Windows")) {
+ keytoolCommand = "keytool.exe";
+ } else {
+ keytoolCommand = "keytool";
+ }
+
+ String javaHome = System.getProperty("java.home");
+
+ if (javaHome != null && javaHome.length() > 0) {
+ keytoolCommand = javaHome + File.separator + "bin" + File.separator + keytoolCommand;
+ }
+
+ // create the command line to call key tool to build the key with no user input.
+ ArrayList<String> commandList = new ArrayList<String>();
+ commandList.add(keytoolCommand);
+ commandList.add("-genkey");
+ commandList.add("-alias");
+ commandList.add(alias);
+ commandList.add("-keyalg");
+ commandList.add("RSA");
+ commandList.add("-dname");
+ commandList.add(description);
+ commandList.add("-validity");
+ commandList.add(Integer.toString(validityYears * 365));
+ commandList.add("-keypass");
+ commandList.add(keyPassword);
+ commandList.add("-keystore");
+ commandList.add(osKeyStorePath);
+ commandList.add("-storepass");
+ commandList.add(storePassword);
+ if (storeType != null) {
+ commandList.add("-storetype");
+ commandList.add(storeType);
+ }
+
+ String[] commandArray = commandList.toArray(new String[commandList.size()]);
+
+ // launch the command line process
+ int result = 0;
+ try {
+ result = grabProcessOutput(Runtime.getRuntime().exec(commandArray), output);
+ } catch (Exception e) {
+ // create the command line as one string
+ StringBuilder builder = new StringBuilder();
+ boolean firstArg = true;
+ for (String arg : commandArray) {
+ boolean hasSpace = arg.indexOf(' ') != -1;
+
+ if (firstArg == true) {
+ firstArg = false;
+ } else {
+ builder.append(' ');
+ }
+
+ if (hasSpace) {
+ builder.append('"');
+ }
+
+ builder.append(arg);
+
+ if (hasSpace) {
+ builder.append('"');
+ }
+ }
+
+ throw new KeytoolException("Failed to create key: " + e.getMessage(),
+ javaHome, builder.toString());
+ }
+
+ if (result != 0) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Get the stderr/stdout outputs of a process and return when the process is done.
+ * Both <b>must</b> be read or the process will block on windows.
+ * @param process The process to get the ouput from
+ * @return the process return code.
+ * @throws InterruptedException
+ */
+ private static int grabProcessOutput(final Process process, final IKeyGenOutput output) {
+ // read the lines as they come. if null is returned, it's
+ // because the process finished
+ Thread t1 = new Thread("") {
+ @Override
+ public void run() {
+ // create a buffer to read the stderr output
+ InputStreamReader is = new InputStreamReader(process.getErrorStream());
+ BufferedReader errReader = new BufferedReader(is);
+
+ try {
+ while (true) {
+ String line = errReader.readLine();
+ if (line != null) {
+ if (output != null) {
+ output.err(line);
+ } else {
+ System.err.println(line);
+ }
+ } else {
+ break;
+ }
+ }
+ } catch (IOException e) {
+ // do nothing.
+ }
+ }
+ };
+
+ Thread t2 = new Thread("") {
+ @Override
+ public void run() {
+ InputStreamReader is = new InputStreamReader(process.getInputStream());
+ BufferedReader outReader = new BufferedReader(is);
+
+ try {
+ while (true) {
+ String line = outReader.readLine();
+ if (line != null) {
+ if (output != null) {
+ output.out(line);
+ } else {
+ System.out.println(line);
+ }
+ } else {
+ break;
+ }
+ }
+ } catch (IOException e) {
+ // do nothing.
+ }
+ }
+ };
+
+ t1.start();
+ t2.start();
+
+ // it looks like on windows process#waitFor() can return
+ // before the thread have filled the arrays, so we wait for both threads and the
+ // process itself.
+ try {
+ t1.join();
+ } catch (InterruptedException e) {
+ }
+ try {
+ t2.join();
+ } catch (InterruptedException e) {
+ }
+
+ // get the return code from the process
+ try {
+ return process.waitFor();
+ } catch (InterruptedException e) {
+ // since we're waiting for the output thread above, we should never actually wait
+ // on the process to end, since it'll be done by the time we call waitFor()
+ return 0;
+ }
+ }
+}
diff --git a/tools/runtest b/tools/runtest
index d7beefe..cc6444b 100755
--- a/tools/runtest
+++ b/tools/runtest
@@ -16,13 +16,15 @@
# Options and default values
# TODO: other options ideas:
-# pass options to am
+# pass options to am (then remove some of the more specific options)
# TODO capture more non-error output when not -v
+# TODO read configs from vendor/*, not just from vendor/google
optListTests=0
optSkipBuild=0
optPreview=0
optRawmode=0
+optSuiteAssignmentMode=0
optAdbTarget=""
optVerbose=0
optWaitForDebugger=0
@@ -35,12 +37,13 @@
# TODO error messages on once-only or mutually-exclusive options
#
function processOptions() {
- while getopts "l b n r d e s: v w c:t:u:" opt ; do
+ while getopts "l b n a r d e s: v w c:t:u:" opt ; do
case ${opt} in
l ) optListTests=1 ;;
b ) optSkipBuild=1 ;;
n ) optPreview=1 ;;
r ) optRawMode=1 ;;
+ a ) optSuiteAssignmentMode=1 ;;
d ) optAdbTarget="-d" ;;
e ) optAdbTarget="-e" ;;
s ) optAdbTarget="-s ${OPTARG}" ;;
@@ -53,6 +56,30 @@
done
}
+#
+# Show the command usage and options
+#
+function showUsage() {
+ echo "usage: The $progName script works in two ways. You can query it for a list" >&2
+ echo " of tests, or you can launch a test, test case, or test suite." >&2
+ echo "" >&2
+ echo " $progName -l # To view the list of tests" >&2
+ echo "" >&2
+ echo " $progName # To launch tests" >&2
+ echo " [-b] # Skip build - just launch" >&2
+ echo " [-n] # Do not execute, just preview commands" >&2
+ echo " [-r] # Raw mode (for output to other tools)" >&2
+ echo " [-a] # Suite assignment (for details & usage" >&2
+ echo " # see InstrumentationTestRunner)" >&2
+ echo " [-v] # Increase verbosity of ${progName}" >&2
+ echo " [-w] # Wait for debugger before launching tests" >&2
+ echo " [-c test-class] # Restrict test to a specific class" >&2
+ echo " [-t test-method] # Restrict test to a specific method" >&2
+ echo " [-e | -d | -s ser-num] # use emulator, device, or serial number" >&2
+ echo " [-u user-tests-file] # Alternate source of user definitions" >&2
+ echo " short-test-name # (req'd) test configuration to launch" >&2
+}
+
# The list below are built-in test definitions. You can also define your own
# tests by creating a file named "~/.android/runtest.rc" and adding them to that
# file. (No array needed, just plain lines of text).
@@ -85,50 +112,50 @@
# NAME BUILD DIR <test-package> <test-class> <testrunner-package> <testrunner-component>
# system-wide tests
- "framework tests/FrameworkTests # com.android.frameworktest.AllTests com.android.frameworktest.tests #"
- "core java/tests android.core CoreTests # #"
- "android apps/AndroidTests com.android.unit_tests AndroidTests # #"
- "smoke tests/SmokeTest com.android.smoketest # com.android.smoketest.tests #"
- "libcore java/tests/android android.core JavaTests # #"
- "apidemos samples/ApiDemos com.example.android.apis # com.example.android.apis.tests #"
+ "framework frameworks/base/tests/FrameworkTest # com.android.frameworktest.AllTests com.android.frameworktest.tests #"
+ "android frameworks/base/tests/AndroidTests com.android.unit_tests AndroidTests # #"
+ "smoke tests/SmokeTest com.android.smoketest # com.android.smoketest.tests #"
+ "core frameworks/base/tests/CoreTests # android.core.CoreTests android.core #"
+ "libcore frameworks/base/tests/CoreTests # android.core.JavaTests android.core #"
+ "apidemos samples/ApiDemos com.example.android.apis # com.example.android.apis.tests #"
# targeted framework tests
- "heap apps/AndroidTests com.android.unit_tests HeapTest # #"
- "activity apps/AndroidTests com.android.unit_tests activity.ActivityTests # #"
- "deadlock tests/Deadlock com.android.deadlock # com.android.deadlock.tests #"
+ "heap frameworks/base/tests/AndroidTests com.android.unit_tests HeapTest # #"
+ "activity frameworks/base/tests/AndroidTests com.android.unit_tests activity.ActivityTests # #"
+ "deadlock tests/Deadlock com.android.deadlock # com.android.deadlock.tests #"
# selected app tests
- "browser apps/Browser com.android.browser # # .BrowserTestRunner"
- "browserfunc apps/Browser com.android.browser # # .BrowserFunctionalTestRunner"
- "calendar apps/Calendar/tests com.android.calendar.tests # # #"
+ "browser packages/apps/Browser com.android.browser # # .BrowserTestRunner"
+ "browserfunc packages/apps/Browser com.android.browser # # .BrowserFunctionalTestRunner"
+ "calendar packages/apps/Calendar/tests com.android.calendar.tests # # #"
"calprov content/providers/calendar com.android.providers.calendar.tests # # #"
"camera tests/Camera com.android.cameratests # # CameraInstrumentationTestRunner"
"contactsprov content/tests/providers/contacts com.android.providers.contacts # com.android.providers.contactstests .ContactsProviderInstrumentation"
- "gmail partner/google/tests/Gmail com.google.android.gmailtests # # .GmailTestRunner"
- "gmailprov partner/google/tests/GmailProvider com.google.android.gmailprovidertests # # #"
- "maps partner/google/tests/Maps com.google.android.mapstests # # .MapInstrumentationTestRunner"
- "mapsapi partner/google/tests/Maps com.google.android.mapstests # # .MapApiInstrumentationTestRunner"
+ "email packages/apps/Email com.android.email # com.android.email.tests #"
+ "emailsmall packages/apps/Email com.android.email SmallTests com.android.email.tests #"
"media tests/MediaFrameworkTest com.android.mediaframeworktest # # .MediaFrameworkTestRunner"
"mediaunit tests/MediaFrameworkTest com.android.mediaframeworktest # # .MediaFrameworkUnitTestRunner"
"mediaprov tests/MediaProvider com.android.mediaprovidertests # # .MediaProviderTestsInstrumentation"
- "mms apps/Mms # # com.android.mms.tests com.android.mms.ui.MMSInstrumentationTestRunner"
- "mmslaunch apps/Mms # # com.android.mms.tests com.android.mms.SmsLaunchPerformance"
+ "mms packages/apps/Mms # # com.android.mms.tests com.android.mms.ui.MMSInstrumentationTestRunner"
+ "mmslaunch packages/apps/Mms # # com.android.mms.tests com.android.mms.SmsLaunchPerformance"
"phone tests/Phone com.android.phonetests # # .PhoneInstrumentationTestRunner"
"phonestress tests/Phone com.android.phonetests # # .PhoneInstrumentationStressTestRunner"
"ringtone tests/RingtoneSettings com.android.ringtonesettingstests # # .RingtoneSettingsInstrumentationTestRunner"
- "vending partner/google/apps/Vending/tests com.android.vendingtests # # #"
- "youtube partner/google/apps/YouTube/ com.google.android.youtube # # .YouTubeTestRunner"
)
#
-# Searches for a user-defined test file (~/.android/runtest.rc and, if found,
-# prepends any test definitions to the master list in knownTests.
-# TODO allow override filename to be set by option
+# Searches for a runtest.rc file in a given directory and, if found, prepends it to
+# the list of known tests.
#
-function setupInputArray() {
- if [[ -f ${optUserTests} ]] ; then
+function readConfigFile () {
+ pathToRc=$1
+ if [[ -z ${pathToRc} ]]; then
+ exit 0
+ fi
+ rcFile=${pathToRc}/runtest.rc
+ if [[ -f ${rcFile} ]] ; then
declare -a lines
- exec 3<${optUserTests} || exit
+ exec 3<${rcFile} || exit
while read curline <&3; do
if [[ -z ${curline} || ${curline:0:1} = "#" ]]; then
continue
@@ -182,7 +209,7 @@
# (based on gettop() from envsetup.sh)
#
function gettop {
- TOPFILE=config/envsetup.make
+ TOPFILE=build/core/envsetup.mk
if [[ -n ${TOP} && -f ${TOP}/${TOPFILE} ]] ; then
echo ${TOP}
else
@@ -211,10 +238,10 @@
# Captures the "mmm" command from envsetup.sh
#
function call_mmm() {
- T=$(gettop)
- if [[ -n ${T} ]] ; then
- . ${T}/envsetup.sh
- mmm ${T}/$@
+ TOP=$(gettop)
+ if [[ -n ${TOP} ]] ; then
+ . ${TOP}/build/envsetup.sh
+ mmm ${TOP}/$@
fi
}
@@ -223,20 +250,16 @@
progName=$(basename $0)
if [[ $# -eq 0 ]] ; then
- echo "usage: $progName -l" >&2
- echo " $progName [-b] [-p] [-n] [-r] [-v]" >&2
- echo " [-u <user-tests-file>]" >&2
- echo " [-c test-class]" >&2
- echo " [-t test-method]" >&2
- echo " [-d | -e | -s serial-number]" >&2
- echo " <short-test-name>" >&2
+ showUsage
exit 1
fi
processOptions $@
shift $((OPTIND-1))
-setupInputArray
+readConfigFile $optUserTests
+# TODO: Read from *any* vendor/*/runtest.rc
+readConfigFile $(gettop)/vendor/google
# if requested, list all tests and halt
if [[ ${optListTests} -ne 0 ]] ; then
@@ -272,10 +295,10 @@
if [[ ${optSkipBuild} -eq 0 ]] ; then
if [[ ${buildPath} != "#" ]] ; then
if [[ $optVerbose -ne 0 || ${optPreview} -ne 0 ]] ; then
- echo mmm ${buildPath} "&&" adb ${optAdbTarget} sync
+ echo mmm ${buildPath} "&&" adb ${optAdbTarget} remount "&&" adb ${optAdbTarget} sync
fi
if [[ ${optPreview} -eq 0 ]] ; then
- call_mmm ${buildPath} && adb ${optAdbTarget} sync
+ call_mmm ${buildPath} && adb ${optAdbTarget} remount && adb ${optAdbTarget} sync
buildResult=$?
else
buildResult=0
@@ -283,6 +306,10 @@
if [[ $buildResult -ne 0 ]] ; then
exit ${buildResult}
fi
+ # finally, sleep a bit. this is a hack. it gives the package manager time to
+ # install the package(s) that were just synced. this causes a reduction in the number
+ # of false failures, but it's not a perfect solution.
+ sleep 2
fi
fi
@@ -302,6 +329,9 @@
if [[ ${optWaitForDebugger} -ne 0 ]] ; then
debugOptions="-e debug true"
fi
+ if [[ ${optSuiteAssignmentMode} -ne 0 ]] ; then
+ debugOptions="-e suiteAssignment true "${debugOptions}
+ fi
if [[ ${optRawMode} -ne 0 ]] ; then
debugOptions="-r "${debugOptions}
fi
diff --git a/tools/scripts/AndroidManifest.tests.template b/tools/scripts/AndroidManifest.tests.template
new file mode 100644
index 0000000..1f7d827
--- /dev/null
+++ b/tools/scripts/AndroidManifest.tests.template
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="PACKAGE.tests"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <!-- We add an application tag here just so that we can indicate that
+ this package needs to link against the android.test library,
+ which is needed when building test cases. -->
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+ <!--
+ This declares that this application uses the instrumentation test runner targeting
+ the package of PACKAGE. To run the tests use the command:
+ "adb shell am instrument -w PACKAGE.tests/android.test.InstrumentationTestRunner"
+ -->
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="PACKAGE"
+ android:label="Tests for ACTIVITY_NAME"/>
+</manifest>
diff --git a/tools/scripts/README_add-ons.txt b/tools/scripts/README_add-ons.txt
new file mode 100644
index 0000000..b8eb1d6
--- /dev/null
+++ b/tools/scripts/README_add-ons.txt
@@ -0,0 +1,2 @@
+Add-on folder.
+Drop vendor supplied SDK add-on in this folder.
\ No newline at end of file
diff --git a/tools/scripts/alias_rules.xml b/tools/scripts/alias_rules.xml
new file mode 100644
index 0000000..0443193
--- /dev/null
+++ b/tools/scripts/alias_rules.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" ?>
+<project name="alias_rules" default="package">
+
+ <!-- No user servicable parts below. -->
+
+ <!-- Input directories -->
+ <property name="resource-dir" value="res" />
+
+ <!-- The final package file to generate -->
+ <property name="out-package" value="${ant.project.name}.apk" />
+
+ <!-- Tools -->
+ <condition property="aapt" value="${android-tools}/aapt.exe" else="${android-tools}/aapt" >
+ <os family="windows"/>
+ </condition>
+ <condition property="adb" value="${android-tools}/adb.exe" else="${android-tools}/adb" >
+ <os family="windows"/>
+ </condition>
+ <property name="android-jar" value="${sdk-folder}/android.jar" />
+
+ <!-- Rules -->
+
+ <!-- Packages the manifest and the resource files -->
+ <target name="package-res">
+ <echo>Packaging resources...</echo>
+ <exec executable="${aapt}" failonerror="true">
+ <arg value="package" />
+ <arg value="-f" />
+ <arg value="-M" />
+ <arg value="AndroidManifest.xml" />
+ <arg value="-S" />
+ <arg value="${resource-dir}" />
+ <arg value="-I" />
+ <arg value="${android-jar}" />
+ <arg value="-F" />
+ <arg value="${out-package}" />
+ </exec>
+ </target>
+
+ <!-- Create the package file for this project from the sources. -->
+ <target name="package" depends="package-res" />
+
+ <!-- Create the package and install package on the default emulator -->
+ <target name="install" depends="package">
+ <echo>Sending package to default emulator...</echo>
+ <exec executable="${adb}" failonerror="true">
+ <arg value="install" />
+ <arg value="${out-package}" />
+ </exec>
+ </target>
+
+</project>
diff --git a/tools/scripts/android_rules.xml b/tools/scripts/android_rules.xml
new file mode 100644
index 0000000..bed5f24
--- /dev/null
+++ b/tools/scripts/android_rules.xml
@@ -0,0 +1,280 @@
+<?xml version="1.0" ?>
+<project name="android_rules" default="debug">
+
+ <!-- No user servicable parts below. -->
+
+ <property name="outdir-main" value="../${outdir}" />
+
+ <property name="android-tools" value="${sdk-folder}/tools" />
+ <property name="android-platform" value="${sdk-folder}/platforms/${target-folder}" />
+ <property name="android-framework" value="${android-platform}/framework.aidl" />
+ <property name="android-jar" value="${android-platform}/android.jar" />
+
+ <!-- Input directories -->
+ <property name="resource-dir" value="res" />
+ <property name="asset-dir" value="assets" />
+ <property name="srcdir" value="src" />
+ <condition property="srcdir-ospath"
+ value="${basedir}\${srcdir}"
+ else="${basedir}/${srcdir}" >
+ <os family="windows"/>
+ </condition>
+
+ <!-- folder for the 3rd party java libraries -->
+ <property name="external-libs" value="libs" />
+ <condition property="external-libs-ospath"
+ value="${basedir}\${external-libs}"
+ else="${basedir}/${external-libs}" >
+ <os family="windows"/>
+ </condition>
+
+ <!-- folder for the native libraries -->
+ <property name="native-libs" value="libs" />
+ <condition property="native-libs-ospath"
+ value="${basedir}\${native-libs}"
+ else="${basedir}/${native-libs}" >
+ <os family="windows"/>
+ </condition>
+
+ <!-- Output directories -->
+ <property name="outdir-classes" value="${outdir}/classes" />
+ <condition property="outdir-classes-ospath"
+ value="${basedir}\${outdir-classes}"
+ else="${basedir}/${outdir-classes}" >
+ <os family="windows"/>
+ </condition>
+ <condition property="outdir-main-classes"
+ value="${outdir-main}/classes">
+ <available file="${outdir-main}/classes"
+ type="dir"/>
+ </condition>
+
+ <!-- Create R.java in the source directory -->
+ <property name="outdir-r" value="src" />
+
+ <!-- Intermediate files -->
+ <property name="dex-file" value="classes.dex" />
+ <property name="intermediate-dex" value="${outdir}/${dex-file}" />
+ <condition property="intermediate-dex-ospath"
+ value="${basedir}\${intermediate-dex}"
+ else="${basedir}/${intermediate-dex}" >
+ <os family="windows"/>
+ </condition>
+
+ <!-- The final package file to generate -->
+ <property name="resources-package" value="${outdir}/${ant.project.name}.ap_" />
+ <condition property="resources-package-ospath"
+ value="${basedir}\${resources-package}"
+ else="${basedir}/${resources-package}" >
+ <os family="windows"/>
+ </condition>
+
+ <property name="out-debug-package" value="${outdir}/${ant.project.name}-debug.apk" />
+ <condition property="out-debug-package-ospath"
+ value="${basedir}\${out-debug-package}"
+ else="${basedir}/${out-debug-package}" >
+ <os family="windows"/>
+ </condition>
+
+ <property name="out-unsigned-package" value="${outdir}/${ant.project.name}-unsigned.apk" />
+ <condition property="out-unsigned-package-ospath"
+ value="${basedir}\${out-unsigned-package}"
+ else="${basedir}/${out-unsigned-package}" >
+ <os family="windows"/>
+ </condition>
+
+ <!-- Tools -->
+ <condition property="aapt" value="${android-tools}/aapt.exe" else="${android-tools}/aapt" >
+ <os family="windows"/>
+ </condition>
+ <condition property="aidl" value="${android-tools}/aidl.exe" else="${android-tools}/aidl" >
+ <os family="windows"/>
+ </condition>
+ <condition property="adb" value="${android-tools}/adb.exe" else="${android-tools}/adb" >
+ <os family="windows"/>
+ </condition>
+ <condition property="dx" value="${android-tools}/dx.bat" else="${android-tools}/dx" >
+ <os family="windows"/>
+ </condition>
+ <condition property="apk-builder" value="${android-tools}/apkbuilder.bat" else="${android-tools}/apkbuilder" >
+ <os family="windows"/>
+ </condition>
+
+ <!-- Rules -->
+
+ <!-- Create the output directories if they don't exist yet. -->
+ <target name="dirs">
+ <echo>Creating output directories if needed...</echo>
+ <mkdir dir="${outdir}" />
+ <mkdir dir="${outdir-classes}" />
+ </target>
+
+ <!-- Generate the R.java file for this project's resources. -->
+ <target name="resource-src" depends="dirs">
+ <echo>Generating R.java / Manifest.java from the resources...</echo>
+ <exec executable="${aapt}" failonerror="true">
+ <arg value="package" />
+ <arg value="-m" />
+ <arg value="-J" />
+ <arg value="${outdir-r}" />
+ <arg value="-M" />
+ <arg value="AndroidManifest.xml" />
+ <arg value="-S" />
+ <arg value="${resource-dir}" />
+ <arg value="-I" />
+ <arg value="${android-jar}" />
+ </exec>
+ </target>
+
+ <!-- Generate java classes from .aidl files. -->
+ <target name="aidl" depends="dirs">
+ <echo>Compiling aidl files into Java classes...</echo>
+ <apply executable="${aidl}" failonerror="true">
+ <arg value="-p${android-framework}" />
+ <arg value="-I${srcdir}" />
+ <fileset dir="${srcdir}">
+ <include name="**/*.aidl"/>
+ </fileset>
+ </apply>
+ </target>
+
+ <!-- Compile this project's .java files into .class files. -->
+ <target name="compile" depends="dirs, resource-src, aidl">
+ <javac encoding="ascii" target="1.5" debug="true" extdirs=""
+ srcdir="${srcdir}"
+ destdir="${outdir-classes}"
+ bootclasspath="${android-jar}">
+ <classpath>
+ <fileset dir="${external-libs}" includes="*.jar"/>
+ <pathelement path="${outdir-main-classes}"/>
+ </classpath>
+ </javac>
+ </target>
+
+ <!-- Convert this project's .class files into .dex files. -->
+ <target name="dex" depends="compile">
+ <echo>Converting compiled files and external libraries into ${outdir}/${dex-file}...</echo>
+ <apply executable="${dx}" failonerror="true" parallel="true">
+ <arg value="--dex" />
+ <arg value="--output=${intermediate-dex-ospath}" />
+ <arg path="${outdir-classes-ospath}" />
+ <fileset dir="${external-libs}" includes="*.jar"/>
+ </apply>
+ </target>
+
+ <!-- Put the project's resources into the output package file. -->
+ <target name="package-res-and-assets">
+ <echo>Packaging resources and assets...</echo>
+ <exec executable="${aapt}" failonerror="true">
+ <arg value="package" />
+ <arg value="-f" />
+ <arg value="-M" />
+ <arg value="AndroidManifest.xml" />
+ <arg value="-S" />
+ <arg value="${resource-dir}" />
+ <arg value="-A" />
+ <arg value="${asset-dir}" />
+ <arg value="-I" />
+ <arg value="${android-jar}" />
+ <arg value="-F" />
+ <arg value="${resources-package}" />
+ </exec>
+ </target>
+
+ <!-- Same as package-res-and-assets, but without "-A ${asset-dir}" -->
+ <target name="package-res-no-assets">
+ <echo>Packaging resources...</echo>
+ <exec executable="${aapt}" failonerror="true">
+ <arg value="package" />
+ <arg value="-f" />
+ <arg value="-M" />
+ <arg value="AndroidManifest.xml" />
+ <arg value="-S" />
+ <arg value="${resource-dir}" />
+ <!-- No assets directory -->
+ <arg value="-I" />
+ <arg value="${android-jar}" />
+ <arg value="-F" />
+ <arg value="${resources-package}" />
+ </exec>
+ </target>
+
+ <!-- Invoke the proper target depending on whether or not
+ an assets directory is present. -->
+ <!-- TODO: find a nicer way to include the "-A ${asset-dir}" argument
+ only when the assets dir exists. -->
+ <target name="package-res">
+ <available file="${asset-dir}" type="dir"
+ property="res-target" value="and-assets" />
+ <property name="res-target" value="no-assets" />
+ <antcall target="package-res-${res-target}" />
+ </target>
+
+ <!-- Package the application and sign it with a debug key.
+ This is the default target when building. It is used for debug. -->
+ <target name="debug" depends="dex, package-res">
+ <echo>Packaging ${out-debug-package}, and signing it with a debug key...</echo>
+ <exec executable="${apk-builder}" failonerror="true">
+ <arg value="${out-debug-package-ospath}" />
+ <arg value="-z" />
+ <arg value="${resources-package-ospath}" />
+ <arg value="-f" />
+ <arg value="${intermediate-dex-ospath}" />
+ <arg value="-rf" />
+ <arg value="${srcdir-ospath}" />
+ <arg value="-rj" />
+ <arg value="${external-libs-ospath}" />
+ <arg value="-nf" />
+ <arg value="${native-libs-ospath}" />
+ </exec>
+ </target>
+
+ <!-- Package the application without signing it.
+ This allows for the application to be signed later with an official publishing key. -->
+ <target name="release" depends="dex, package-res">
+ <echo>Packaging ${out-unsigned-package} for release...</echo>
+ <exec executable="${apk-builder}" failonerror="true">
+ <arg value="${out-unsigned-package-ospath}" />
+ <arg value="-u" />
+ <arg value="-z" />
+ <arg value="${resources-package-ospath}" />
+ <arg value="-f" />
+ <arg value="${intermediate-dex-ospath}" />
+ <arg value="-rf" />
+ <arg value="${srcdir-ospath}" />
+ <arg value="-rj" />
+ <arg value="${external-libs-ospath}" />
+ <arg value="-nf" />
+ <arg value="${native-libs-ospath}" />
+ </exec>
+ <echo>It will need to be signed with jarsigner before being published.</echo>
+ </target>
+
+ <!-- Install the package on the default emulator -->
+ <target name="install" depends="debug">
+ <echo>Installing ${out-debug-package} onto default emulator...</echo>
+ <exec executable="${adb}" failonerror="true">
+ <arg value="install" />
+ <arg value="${out-debug-package}" />
+ </exec>
+ </target>
+
+ <target name="reinstall" depends="debug">
+ <echo>Installing ${out-debug-package} onto default emulator...</echo>
+ <exec executable="${adb}" failonerror="true">
+ <arg value="install" />
+ <arg value="-r" />
+ <arg value="${out-debug-package}" />
+ </exec>
+ </target>
+
+ <!-- Uinstall the package from the default emulator -->
+ <target name="uninstall">
+ <echo>Uninstalling ${application-package} from the default emulator...</echo>
+ <exec executable="${adb}" failonerror="true">
+ <arg value="uninstall" />
+ <arg value="${application-package}" />
+ </exec>
+ </target>
+
+</project>
diff --git a/tools/scripts/build.alias.template b/tools/scripts/build.alias.template
index 22252aa..b85887e 100644
--- a/tools/scripts/build.alias.template
+++ b/tools/scripts/build.alias.template
@@ -11,52 +11,9 @@
<property file="default.properties"/>
<!-- ************************************************************************************* -->
- <!-- No user servicable parts below. -->
+ <!-- Import the default Android build rules.
+ This requires ant 1.6.0 or above. -->
- <!-- Input directories -->
- <property name="resource-dir" value="res" />
-
- <!-- The final package file to generate -->
- <property name="out-package" value="${ant.project.name}.apk" />
-
- <!-- Tools -->
- <condition property="aapt" value="${android-tools}/aapt.exe" else="${android-tools}/aapt" >
- <os family="windows"/>
- </condition>
- <condition property="adb" value="${android-tools}/adb.exe" else="${android-tools}/adb" >
- <os family="windows"/>
- </condition>
- <property name="android-jar" value="${sdk-folder}/android.jar" />
-
- <!-- Rules -->
-
- <!-- Packages the manifest and the resource files -->
- <target name="package-res">
- <echo>Packaging resources...</echo>
- <exec executable="${aapt}" failonerror="true">
- <arg value="package" />
- <arg value="-f" />
- <arg value="-M" />
- <arg value="AndroidManifest.xml" />
- <arg value="-S" />
- <arg value="${resource-dir}" />
- <arg value="-I" />
- <arg value="${android-jar}" />
- <arg value="-F" />
- <arg value="${out-package}" />
- </exec>
- </target>
-
- <!-- Create the package file for this project from the sources. -->
- <target name="package" depends="package-res" />
-
- <!-- Create the package and install package on the default emulator -->
- <target name="install" depends="package">
- <echo>Sending package to default emulator...</echo>
- <exec executable="${adb}" failonerror="true">
- <arg value="install" />
- <arg value="${out-package}" />
- </exec>
- </target>
+ <import file="${sdk-folder}/tools/lib/alias_rules.xml" />
</project>
diff --git a/tools/scripts/build.template b/tools/scripts/build.template
index 0081c33..f04f1d8 100644
--- a/tools/scripts/build.template
+++ b/tools/scripts/build.template
@@ -22,272 +22,9 @@
<property name="outdir" value="bin" />
<!-- ************************************************************************************* -->
- <!-- No user servicable parts below. -->
+ <!-- Import the default Android build rules.
+ This requires ant 1.6.0 or above. -->
- <property name="android-tools" value="${sdk-folder}/tools" />
- <property name="android-framework" value="${android-tools}/lib/framework.aidl" />
-
- <!-- Input directories -->
- <property name="resource-dir" value="res" />
- <property name="asset-dir" value="assets" />
- <property name="srcdir" value="src" />
- <condition property="srcdir-ospath"
- value="${basedir}\${srcdir}"
- else="${basedir}/${srcdir}" >
- <os family="windows"/>
- </condition>
-
- <!-- folder for the 3rd party java libraries -->
- <property name="external-libs" value="libs" />
- <condition property="external-libs-ospath"
- value="${basedir}\${external-libs}"
- else="${basedir}/${external-libs}" >
- <os family="windows"/>
- </condition>
-
- <!-- folder for the native libraries -->
- <property name="native-libs" value="libs" />
- <condition property="native-libs-ospath"
- value="${basedir}\${native-libs}"
- else="${basedir}/${native-libs}" >
- <os family="windows"/>
- </condition>
-
- <!-- Output directories -->
- <property name="outdir-classes" value="${outdir}/classes" />
- <condition property="outdir-classes-ospath"
- value="${basedir}\${outdir-classes}"
- else="${basedir}/${outdir-classes}" >
- <os family="windows"/>
- </condition>
-
- <!-- Create R.java in the source directory -->
- <property name="outdir-r" value="src" />
-
- <!-- Intermediate files -->
- <property name="dex-file" value="classes.dex" />
- <property name="intermediate-dex" value="${outdir}/${dex-file}" />
- <condition property="intermediate-dex-ospath"
- value="${basedir}\${intermediate-dex}"
- else="${basedir}/${intermediate-dex}" >
- <os family="windows"/>
- </condition>
-
- <!-- The final package file to generate -->
- <property name="resources-package" value="${outdir}/${ant.project.name}.ap_" />
- <condition property="resources-package-ospath"
- value="${basedir}\${resources-package}"
- else="${basedir}/${resources-package}" >
- <os family="windows"/>
- </condition>
-
- <property name="out-debug-package" value="${outdir}/${ant.project.name}-debug.apk" />
- <condition property="out-debug-package-ospath"
- value="${basedir}\${out-debug-package}"
- else="${basedir}/${out-debug-package}" >
- <os family="windows"/>
- </condition>
-
- <property name="out-unsigned-package" value="${outdir}/${ant.project.name}-unsigned.apk" />
- <condition property="out-unsigned-package-ospath"
- value="${basedir}\${out-unsigned-package}"
- else="${basedir}/${out-unsigned-package}" >
- <os family="windows"/>
- </condition>
-
- <!-- Tools -->
- <condition property="aapt" value="${android-tools}/aapt.exe" else="${android-tools}/aapt" >
- <os family="windows"/>
- </condition>
- <condition property="aidl" value="${android-tools}/aidl.exe" else="${android-tools}/aidl" >
- <os family="windows"/>
- </condition>
- <condition property="adb" value="${android-tools}/adb.exe" else="${android-tools}/adb" >
- <os family="windows"/>
- </condition>
- <condition property="dx" value="${android-tools}/dx.bat" else="${android-tools}/dx" >
- <os family="windows"/>
- </condition>
- <condition property="apk-builder" value="${android-tools}/apkbuilder.bat" else="${android-tools}/apkbuilder" >
- <os family="windows"/>
- </condition>
-
- <property name="android-jar" value="${sdk-folder}/android.jar" />
-
- <!-- Rules -->
-
- <!-- Create the output directories if they don't exist yet. -->
- <target name="dirs">
- <echo>Creating output directories if needed...</echo>
- <mkdir dir="${outdir}" />
- <mkdir dir="${outdir-classes}" />
- </target>
-
- <!-- Generate the R.java file for this project's resources. -->
- <target name="resource-src" depends="dirs">
- <echo>Generating R.java / Manifest.java from the resources...</echo>
- <exec executable="${aapt}" failonerror="true">
- <arg value="package" />
- <arg value="-m" />
- <arg value="-J" />
- <arg value="${outdir-r}" />
- <arg value="-M" />
- <arg value="AndroidManifest.xml" />
- <arg value="-S" />
- <arg value="${resource-dir}" />
- <arg value="-I" />
- <arg value="${android-jar}" />
- </exec>
- </target>
-
- <!-- Generate java classes from .aidl files. -->
- <target name="aidl" depends="dirs">
- <echo>Compiling aidl files into Java classes...</echo>
- <apply executable="${aidl}" failonerror="true">
- <arg value="-p${android-framework}" />
- <arg value="-I${srcdir}" />
- <fileset dir="${srcdir}">
- <include name="**/*.aidl"/>
- </fileset>
- </apply>
- </target>
-
- <!-- Compile this project's .java files into .class files. -->
- <target name="compile" depends="dirs, resource-src, aidl">
- <javac encoding="ascii" target="1.5" debug="true" extdirs=""
- srcdir="."
- destdir="${outdir-classes}"
- bootclasspath="${android-jar}">
- <classpath>
- <fileset dir="${external-libs}" includes="*.jar"/>
- </classpath>
- </javac>
- </target>
-
- <!-- Convert this project's .class files into .dex files. -->
- <target name="dex" depends="compile">
- <echo>Converting compiled files and external libraries into ${outdir}/${dex-file}...</echo>
- <apply executable="${dx}" failonerror="true" parallel="true">
- <arg value="--dex" />
- <arg value="--output=${intermediate-dex-ospath}" />
- <arg path="${outdir-classes-ospath}" />
- <fileset dir="${external-libs}" includes="*.jar"/>
- </apply>
- </target>
-
- <!-- Put the project's resources into the output package file. -->
- <target name="package-res-and-assets">
- <echo>Packaging resources and assets...</echo>
- <exec executable="${aapt}" failonerror="true">
- <arg value="package" />
- <arg value="-f" />
- <arg value="-M" />
- <arg value="AndroidManifest.xml" />
- <arg value="-S" />
- <arg value="${resource-dir}" />
- <arg value="-A" />
- <arg value="${asset-dir}" />
- <arg value="-I" />
- <arg value="${android-jar}" />
- <arg value="-F" />
- <arg value="${resources-package}" />
- </exec>
- </target>
-
- <!-- Same as package-res-and-assets, but without "-A ${asset-dir}" -->
- <target name="package-res-no-assets">
- <echo>Packaging resources...</echo>
- <exec executable="${aapt}" failonerror="true">
- <arg value="package" />
- <arg value="-f" />
- <arg value="-M" />
- <arg value="AndroidManifest.xml" />
- <arg value="-S" />
- <arg value="${resource-dir}" />
- <!-- No assets directory -->
- <arg value="-I" />
- <arg value="${android-jar}" />
- <arg value="-F" />
- <arg value="${resources-package}" />
- </exec>
- </target>
-
- <!-- Invoke the proper target depending on whether or not
- an assets directory is present. -->
- <!-- TODO: find a nicer way to include the "-A ${asset-dir}" argument
- only when the assets dir exists. -->
- <target name="package-res">
- <available file="${asset-dir}" type="dir"
- property="res-target" value="and-assets" />
- <property name="res-target" value="no-assets" />
- <antcall target="package-res-${res-target}" />
- </target>
-
- <!-- Package the application and sign it with a debug key.
- This is the default target when building. It is used for debug. -->
- <target name="debug" depends="dex, package-res">
- <echo>Packaging ${out-debug-package}, and signing it with a debug key...</echo>
- <exec executable="${apk-builder}" failonerror="true">
- <arg value="${out-debug-package-ospath}" />
- <arg value="-z" />
- <arg value="${resources-package-ospath}" />
- <arg value="-f" />
- <arg value="${intermediate-dex-ospath}" />
- <arg value="-rf" />
- <arg value="${srcdir-ospath}" />
- <arg value="-rj" />
- <arg value="${external-libs-ospath}" />
- <arg value="-nf" />
- <arg value="${native-libs-ospath}" />
- </exec>
- </target>
-
- <!-- Package the application without signing it.
- This allows for the application to be signed later with an official publishing key. -->
- <target name="release" depends="dex, package-res">
- <echo>Packaging ${out-unsigned-package} for release...</echo>
- <exec executable="${apk-builder}" failonerror="true">
- <arg value="${out-unsigned-package-ospath}" />
- <arg value="-u" />
- <arg value="-z" />
- <arg value="${resources-package-ospath}" />
- <arg value="-f" />
- <arg value="${intermediate-dex-ospath}" />
- <arg value="-rf" />
- <arg value="${srcdir-ospath}" />
- <arg value="-rj" />
- <arg value="${external-libs-ospath}" />
- <arg value="-nf" />
- <arg value="${native-libs-ospath}" />
- </exec>
- <echo>It will need to be signed with jarsigner before being published.</echo>
- </target>
-
- <!-- Install the package on the default emulator -->
- <target name="install" depends="debug">
- <echo>Installing ${out-debug-package} onto default emulator...</echo>
- <exec executable="${adb}" failonerror="true">
- <arg value="install" />
- <arg value="${out-debug-package}" />
- </exec>
- </target>
-
- <target name="reinstall" depends="debug">
- <echo>Installing ${out-debug-package} onto default emulator...</echo>
- <exec executable="${adb}" failonerror="true">
- <arg value="install" />
- <arg value="-r" />
- <arg value="${out-debug-package}" />
- </exec>
- </target>
-
- <!-- Uinstall the package from the default emulator -->
- <target name="uninstall">
- <echo>Uninstalling ${application-package} from the default emulator...</echo>
- <exec executable="${adb}" failonerror="true">
- <arg value="uninstall" />
- <arg value="${application-package}" />
- </exec>
- </target>
+ <import file="${sdk-folder}/tools/lib/android_rules.xml" />
</project>
diff --git a/tools/scripts/combine_sdks.sh b/tools/scripts/combine_sdks.sh
new file mode 100755
index 0000000..89a1141
--- /dev/null
+++ b/tools/scripts/combine_sdks.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+function replace()
+{
+ echo replacing $1
+ rm -rf $UNZIPPED_BASE_DIR/$1
+ cp -rf $UNZIPPED_IMAGE_DIR/$1 $UNZIPPED_BASE_DIR/$1
+}
+
+BASE=$1
+IMAGES=$2
+OUTPUT=$3
+
+if [[ -z $BASE || -z $IMAGES || -z $OUTPUT ]] ; then
+ echo "usage: combine_sdks.sh BASE IMAGES OUTPUT"
+ echo
+ echo " BASE and IMAGES should be sdk zip files. The system image files,"
+ echo " emulator and other runtime files will be copied from IMAGES and"
+ echo " everything else will be copied from BASE. All of this will be"
+ echo " bundled into OUTPUT and zipped up again."
+ echo
+ exit 1
+fi
+
+TMP=$(mktemp -d)
+
+TMP_ZIP=tmp.zip
+
+BASE_DIR=$TMP/base
+IMAGES_DIR=$TMP/images
+OUTPUT_TMP_ZIP=$BASE_DIR/$TMP_ZIP
+
+unzip -q $BASE -d $BASE_DIR
+unzip -q $IMAGES -d $IMAGES_DIR
+
+UNZIPPED_BASE_DIR=$(echo $BASE_DIR/*)
+UNZIPPED_IMAGE_DIR=$(echo $IMAGES_DIR/*)
+
+#
+# The commands to copy over the files that we want
+#
+
+# replace tools/emulator # at this time we do not want the exe from SDK1.x
+replace tools/lib/images
+replace docs
+replace android.jar
+
+#
+# end
+#
+
+pushd $BASE_DIR &> /dev/null
+ # rename the directory to the leaf minus the .zip of OUTPUT
+ LEAF=$(echo $OUTPUT | sed -e "s:.*\.zip/::" | sed -e "s:.zip$::")
+ mv * $LEAF
+ # zip it
+ zip -qr $TMP_ZIP $LEAF
+popd &> /dev/null
+
+cp $OUTPUT_TMP_ZIP $OUTPUT
+
+rm -rf $TMP
diff --git a/tools/scripts/default.properties.template b/tools/scripts/default.properties.template
index 5d708f2..63df494 100644
--- a/tools/scripts/default.properties.template
+++ b/tools/scripts/default.properties.template
@@ -2,4 +2,17 @@
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
# Instead customize values in a "build.properties" file.
+# location of the SDK
sdk-folder=ANDROID_SDK_FOLDER
+
+# target mode. Value can be "platform" or "add-on"
+target-mode=TARGET_MODE
+
+# target API level.
+target-api=TARGET_API
+
+# target name, if target-mode=add-on
+target-name=TARGET_NAME
+
+# target platform. This is either the target itself or the platform the add-on is based on.
+target-folder=TARGET_FOLDER
diff --git a/tools/scripts/divide_and_compress.py b/tools/scripts/divide_and_compress.py
new file mode 100755
index 0000000..d369be4
--- /dev/null
+++ b/tools/scripts/divide_and_compress.py
@@ -0,0 +1,352 @@
+#!/usr/bin/python2.4
+#
+# Copyright (C) 2008 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.
+#
+
+"""Module to compress directories in to series of zip files.
+
+This module will take a directory and compress all its contents, including
+child directories into a series of zip files named N.zip where 'N' ranges from
+0 to infinity. The zip files will all be below a certain specified maximum
+threshold.
+
+The directory is compressed with a depth first traversal, each directory's
+file contents being compressed as it is visisted, before the compression of any
+child directory's contents. In this way the files within an archive are ordered
+and the archives themselves are ordered.
+
+The class also constructs a 'main.py' file intended for use with Google App
+Engine with a custom App Engine program not currently distributed with this
+code base. The custom App Engine runtime can leverage the index files written
+out by this class to more quickly locate which zip file to serve a given URL
+from.
+"""
+
+__author__ = 'jmatt@google.com (Justin Mattson)'
+
+from optparse import OptionParser
+import os
+import stat
+import sys
+import zipfile
+from zipfile import ZipFile
+import divide_and_compress_constants
+
+
+def Main(argv):
+ parser = CreateOptionsParser()
+ (options, args) = parser.parse_args()
+ VerifyArguments(options, parser)
+ zipper = DirectoryZipper(options.destination,
+ options.sourcefiles,
+ ParseSize(options.filesize),
+ options.compress)
+ zipper.StartCompress()
+
+
+def CreateOptionsParser():
+ rtn = OptionParser()
+ rtn.add_option('-s', '--sourcefiles', dest='sourcefiles', default=None,
+ help='The directory containing the files to compress')
+ rtn.add_option('-d', '--destination', dest='destination', default=None,
+ help=('Where to put the archive files, this should not be'
+ ' a child of where the source files exist.'))
+ rtn.add_option('-f', '--filesize', dest='filesize', default='1M',
+ help=('Maximum size of archive files. A number followed by'
+ 'a magnitude indicator, eg. 1000000B == one million '
+ 'BYTES, 500K == five hundred KILOBYTES, 1.2M == one '
+ 'point two MEGABYTES. 1M == 1048576 BYTES'))
+ rtn.add_option('-n', '--nocompress', action='store_false', dest='compress',
+ default=True,
+ help=('Whether the archive files should be compressed, or '
+ 'just a concatenation of the source files'))
+ return rtn
+
+
+def VerifyArguments(options, parser):
+ try:
+ if options.sourcefiles is None or options.destination is None:
+ parser.print_help()
+ sys.exit(-1)
+ except (AttributeError), err:
+ parser.print_help()
+ sys.exit(-1)
+
+
+def ParseSize(size_str):
+ if len(size_str) < 2:
+ raise ValueError(('filesize argument not understood, please include'
+ ' a numeric value and magnitude indicator'))
+ magnitude = size_str[len(size_str)-1:]
+ if not magnitude in ('K', 'B', 'M'):
+ raise ValueError(('filesize magnitude indicator not valid, must be \'K\','
+ '\'B\', or \'M\''))
+ numeral = float(size_str[0:len(size_str)-1])
+ if magnitude == 'K':
+ numeral *= 1024
+ elif magnitude == 'M':
+ numeral *= 1048576
+ return int(numeral)
+
+
+class DirectoryZipper(object):
+ """Class to compress a directory and all its sub-directories."""
+ current_archive = None
+ output_dir = None
+ base_path = None
+ max_size = None
+ compress = None
+ index_fp = None
+
+ def __init__(self, output_path, base_dir, archive_size, enable_compression):
+ """DirectoryZipper constructor.
+
+ Args:
+ output_path: the path to write the archives and index file to
+ base_dir: the directory to compress
+ archive_size: the maximum size, in bytes, of a single archive file
+ enable_compression: whether or not compression should be enabled, if
+ disabled, the files will be written into an uncompresed zip
+ """
+ self.output_dir = output_path
+ self.current_archive = '0.zip'
+ self.base_path = base_dir
+ self.max_size = archive_size
+ self.compress = enable_compression
+
+ def StartCompress(self):
+ """Start compress of the directory.
+
+ This will start the compression process and write the archives to the
+ specified output directory. It will also produce an 'index.txt' file in the
+ output directory that maps from file to archive.
+ """
+ self.index_fp = open(''.join([self.output_dir, 'main.py']), 'w')
+ self.index_fp.write(divide_and_compress_constants.file_preamble)
+ os.path.walk(self.base_path, self.CompressDirectory, 1)
+ self.index_fp.write(divide_and_compress_constants.file_endpiece)
+ self.index_fp.close()
+
+ def RemoveLastFile(self, archive_path=None):
+ """Removes the last item in the archive.
+
+ This removes the last item in the archive by reading the items out of the
+ archive, adding them to a new archive, deleting the old archive, and
+ moving the new archive to the location of the old archive.
+
+ Args:
+ archive_path: Path to the archive to modify. This archive should not be
+ open elsewhere, since it will need to be deleted.
+ Return:
+ A new ZipFile object that points to the modified archive file
+ """
+ if archive_path is None:
+ archive_path = ''.join([self.output_dir, self.current_archive])
+
+ # Move the old file and create a new one at its old location
+ ext_offset = archive_path.rfind('.')
+ old_archive = ''.join([archive_path[0:ext_offset], '-old',
+ archive_path[ext_offset:]])
+ os.rename(archive_path, old_archive)
+ old_fp = self.OpenZipFileAtPath(old_archive, mode='r')
+
+ if self.compress:
+ new_fp = self.OpenZipFileAtPath(archive_path,
+ mode='w',
+ compress=zipfile.ZIP_DEFLATED)
+ else:
+ new_fp = self.OpenZipFileAtPath(archive_path,
+ mode='w',
+ compress=zipfile.ZIP_STORED)
+
+ # Read the old archive in a new archive, except the last one
+ zip_members = enumerate(old_fp.infolist())
+ num_members = len(old_fp.infolist())
+ while num_members > 1:
+ this_member = zip_members.next()[1]
+ new_fp.writestr(this_member.filename, old_fp.read(this_member.filename))
+ num_members -= 1
+
+ # Close files and delete the old one
+ old_fp.close()
+ new_fp.close()
+ os.unlink(old_archive)
+
+ def OpenZipFileAtPath(self, path, mode=None, compress=zipfile.ZIP_DEFLATED):
+ """This method is mainly for testing purposes, eg dependency injection."""
+ if mode is None:
+ if os.path.exists(path):
+ mode = 'a'
+ else:
+ mode = 'w'
+
+ if mode == 'r':
+ return ZipFile(path, mode)
+ else:
+ return ZipFile(path, mode, compress)
+
+ def CompressDirectory(self, irrelevant, dir_path, dir_contents):
+ """Method to compress the given directory.
+
+ This method compresses the directory 'dir_path'. It will add to an existing
+ zip file that still has space and create new ones as necessary to keep zip
+ file sizes under the maximum specified size. This also writes out the
+ mapping of files to archives to the self.index_fp file descriptor
+
+ Args:
+ irrelevant: a numeric identifier passed by the os.path.walk method, this
+ is not used by this method
+ dir_path: the path to the directory to compress
+ dir_contents: a list of directory contents to be compressed
+ """
+
+ # construct the queue of files to be added that this method will use
+ # it seems that dir_contents is given in reverse alphabetical order,
+ # so put them in alphabetical order by inserting to front of the list
+ dir_contents.sort()
+ zip_queue = []
+ if dir_path[len(dir_path) - 1:] == os.sep:
+ for filename in dir_contents:
+ zip_queue.append(''.join([dir_path, filename]))
+ else:
+ for filename in dir_contents:
+ zip_queue.append(''.join([dir_path, os.sep, filename]))
+ compress_bit = zipfile.ZIP_DEFLATED
+ if not self.compress:
+ compress_bit = zipfile.ZIP_STORED
+
+ # zip all files in this directory, adding to existing archives and creating
+ # as necessary
+ while len(zip_queue) > 0:
+ target_file = zip_queue[0]
+ if os.path.isfile(target_file):
+ self.AddFileToArchive(target_file, compress_bit)
+
+ # see if adding the new file made our archive too large
+ if not self.ArchiveIsValid():
+
+ # IF fixing fails, the last added file was to large, skip it
+ # ELSE the current archive filled normally, make a new one and try
+ # adding the file again
+ if not self.FixArchive('SIZE'):
+ zip_queue.pop(0)
+ else:
+ self.current_archive = '%i.zip' % (
+ int(self.current_archive[
+ 0:self.current_archive.rfind('.zip')]) + 1)
+ else:
+
+ # if this the first file in the archive, write an index record
+ self.WriteIndexRecord()
+ zip_queue.pop(0)
+ else:
+ zip_queue.pop(0)
+
+ def WriteIndexRecord(self):
+ """Write an index record to the index file.
+
+ Only write an index record if this is the first file to go into archive
+
+ Returns:
+ True if an archive record is written, False if it isn't
+ """
+ archive = self.OpenZipFileAtPath(
+ ''.join([self.output_dir, self.current_archive]), 'r')
+ archive_index = archive.infolist()
+ if len(archive_index) == 1:
+ self.index_fp.write(
+ '[\'%s\', \'%s\'],\n' % (self.current_archive,
+ archive_index[0].filename))
+ archive.close()
+ return True
+ else:
+ archive.close()
+ return False
+
+ def FixArchive(self, problem):
+ """Make the archive compliant.
+
+ Args:
+ problem: the reason the archive is invalid
+
+ Returns:
+ Whether the file(s) removed to fix the archive could conceivably be
+ in an archive, but for some reason can't be added to this one.
+ """
+ archive_path = ''.join([self.output_dir, self.current_archive])
+ rtn_value = None
+
+ if problem == 'SIZE':
+ archive_obj = self.OpenZipFileAtPath(archive_path, mode='r')
+ num_archive_files = len(archive_obj.infolist())
+
+ # IF there is a single file, that means its too large to compress,
+ # delete the created archive
+ # ELSE do normal finalization
+ if num_archive_files == 1:
+ print ('WARNING: %s%s is too large to store.' % (
+ self.base_path, archive_obj.infolist()[0].filename))
+ archive_obj.close()
+ os.unlink(archive_path)
+ rtn_value = False
+ else:
+ self.RemoveLastFile(''.join([self.output_dir, self.current_archive]))
+ archive_obj.close()
+ print 'Final archive size for %s is %i' % (
+ self.current_archive, os.stat(archive_path)[stat.ST_SIZE])
+ rtn_value = True
+ return rtn_value
+
+ def AddFileToArchive(self, filepath, compress_bit):
+ """Add the file at filepath to the current archive.
+
+ Args:
+ filepath: the path of the file to add
+ compress_bit: whether or not this fiel should be compressed when added
+
+ Returns:
+ True if the file could be added (typically because this is a file) or
+ False if it couldn't be added (typically because its a directory)
+ """
+ curr_archive_path = ''.join([self.output_dir, self.current_archive])
+ if os.path.isfile(filepath):
+ if os.stat(filepath)[stat.ST_SIZE] > 1048576:
+ print 'Warning: %s is potentially too large to serve on GAE' % filepath
+ archive = self.OpenZipFileAtPath(curr_archive_path,
+ compress=compress_bit)
+ # add the file to the archive
+ archive.write(filepath, filepath[len(self.base_path):])
+ archive.close()
+ return True
+ else:
+ return False
+
+ def ArchiveIsValid(self):
+ """Check whether the archive is valid.
+
+ Currently this only checks whether the archive is under the required size.
+ The thought is that eventually this will do additional validation
+
+ Returns:
+ True if the archive is valid, False if its not
+ """
+ archive_path = ''.join([self.output_dir, self.current_archive])
+ if os.stat(archive_path)[stat.ST_SIZE] > self.max_size:
+ return False
+ else:
+ return True
+
+if __name__ == '__main__':
+ Main(sys.argv)
diff --git a/tools/scripts/divide_and_compress_constants.py b/tools/scripts/divide_and_compress_constants.py
new file mode 100644
index 0000000..4e11b6f
--- /dev/null
+++ b/tools/scripts/divide_and_compress_constants.py
@@ -0,0 +1,60 @@
+#!/usr/bin/python2.4
+#
+# Copyright (C) 2008 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.
+#
+
+"""Constants for the divide_and_compress script and DirectoryZipper class."""
+
+__author__ = 'jmatt@google.com (Justin Mattson)'
+
+file_preamble = ('#!/usr/bin/env python\n'
+ '#\n'
+ '# Copyright 2008 Google Inc.\n'
+ '#\n'
+ '# Licensed under the Apache License, Version 2.0 (the'
+ '\"License");\n'
+ '# you may not use this file except in compliance with the '
+ 'License.\n'
+ '# You may obtain a copy of the License at\n'
+ '#\n'
+ '# http://www.apache.org/licenses/LICENSE-2.0\n'
+ '#\n'
+ '# Unless required by applicable law or agreed to in writing,'
+ ' software\n'
+ '# distributed under the License is distributed on an \"AS'
+ 'IS\" BASIS,\n'
+ '# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either '
+ 'express or implied.\n'
+ '# See the License for the specific language governing'
+ ' permissions and\n'
+ '# limitations under the License.\n'
+ '#\n\n'
+ 'import wsgiref.handlers\n'
+ 'from google.appengine.ext import zipserve\n'
+ 'from google.appengine.ext import webapp\n'
+ 'import memcache_zipserve\n\n\n'
+ 'class MainHandler(webapp.RequestHandler):\n\n'
+ ' def get(self):\n'
+ ' self.response.out.write(\'Hello world!\')\n\n'
+ 'def main():\n'
+ ' application = webapp.WSGIApplication([(\'/(.*)\','
+ ' memcache_zipserve.create_handler([')
+
+file_endpiece = ('])),\n'
+ '],\n'
+ 'debug=False)\n'
+ ' wsgiref.handlers.CGIHandler().run(application)\n\n'
+ 'if __name__ == \'__main__\':\n'
+ ' main()')
diff --git a/tools/scripts/java_tests_file.template b/tools/scripts/java_tests_file.template
new file mode 100644
index 0000000..7781a33
--- /dev/null
+++ b/tools/scripts/java_tests_file.template
@@ -0,0 +1,21 @@
+package PACKAGE;
+
+import android.test.ActivityInstrumentationTestCase;
+
+/**
+ * This is a simple framework for a test of an Application. See
+ * {@link android.test.ApplicationTestCase ApplicationTestCase} for more information on
+ * how to write and extend Application tests.
+ * <p/>
+ * To run this test, you can type:
+ * adb shell am instrument -w \
+ * -e class PACKAGE.ACTIVITY_NAMETest \
+ * PACKAGE.tests/android.test.InstrumentationTestRunner
+ */
+public class ACTIVITY_NAMETest extends ActivityInstrumentationTestCase<ACTIVITY_NAME> {
+
+ public ACTIVITY_NAMETest() {
+ super("PACKAGE", ACTIVITY_NAME.class);
+ }
+
+}
\ No newline at end of file
diff --git a/tools/scripts/plugin.prop b/tools/scripts/plugin.prop
index 15593ef..99dba4a 100644
--- a/tools/scripts/plugin.prop
+++ b/tools/scripts/plugin.prop
@@ -1,4 +1,4 @@
# begin plugin.prop
-plugin.version=0.8.0
+plugin.version=0.9.0
plugin.platform=android
# end plugin.prop
\ No newline at end of file
diff --git a/tools/scripts/test_divide_and_compress.py b/tools/scripts/test_divide_and_compress.py
new file mode 100755
index 0000000..d0d27b3
--- /dev/null
+++ b/tools/scripts/test_divide_and_compress.py
@@ -0,0 +1,490 @@
+#!/usr/bin/python2.4
+#
+# Copyright (C) 2008 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.
+#
+
+"""Tests for divide_and_compress.py.
+
+TODO: Add tests for module methods.
+"""
+
+__author__ = 'jmatt@google.com (Justin Mattson)'
+
+import os
+import stat
+import unittest
+import zipfile
+from zipfile import ZipFile
+
+import divide_and_compress
+from mox import mox
+
+
+class BagOfParts(object):
+ """Just a generic class that I can use to assign random attributes to."""
+
+ def NoOp(self):
+ x = 1
+
+
+class ValidAndRemoveTests(unittest.TestCase):
+ """Test the ArchiveIsValid and RemoveLastFile methods."""
+
+ def setUp(self):
+ """Prepare the test.
+
+ Construct some mock objects for use with the tests.
+ """
+ self.my_mox = mox.Mox()
+ file1 = BagOfParts()
+ file1.filename = 'file1.txt'
+ file1.contents = 'This is a test file'
+ file2 = BagOfParts()
+ file2.filename = 'file2.txt'
+ file2.contents = ('akdjfk;djsf;kljdslkfjslkdfjlsfjkdvn;kn;2389rtu4i'
+ 'tn;ghf8:89H*hp748FJw80fu9WJFpwf39pujens;fihkhjfk'
+ 'sdjfljkgsc n;iself')
+ self.files = {'file1': file1, 'file2': file2}
+
+ def testArchiveIsValid(self):
+ """Test the DirectoryZipper.ArchiveIsValid method.
+
+ Run two tests, one that we expect to pass and one that we expect to fail
+ """
+ test_file_size = 1056730
+ self.my_mox.StubOutWithMock(os, 'stat')
+ os.stat('/foo/0.zip').AndReturn([test_file_size])
+ self.my_mox.StubOutWithMock(stat, 'ST_SIZE')
+ stat.ST_SIZE = 0
+ os.stat('/baz/0.zip').AndReturn([test_file_size])
+ mox.Replay(os.stat)
+ test_target = divide_and_compress.DirectoryZipper('/foo/', 'bar',
+ test_file_size - 1, True)
+
+ self.assertEqual(False, test_target.ArchiveIsValid(),
+ msg=('ERROR: Test failed, ArchiveIsValid should have '
+ 'returned false, but returned true'))
+
+ test_target = divide_and_compress.DirectoryZipper('/baz/', 'bar',
+ test_file_size + 1, True)
+ self.assertEqual(True, test_target.ArchiveIsValid(),
+ msg=('ERROR: Test failed, ArchiveIsValid should have'
+ ' returned true, but returned false'))
+
+ def testRemoveLastFile(self):
+ """Test DirectoryZipper.RemoveLastFile method.
+
+ Construct a ZipInfo mock object with two records, verify that write is
+ only called once on the new ZipFile object.
+ """
+ source = self.CreateZipSource()
+ dest = self.CreateZipDestination()
+ source_path = ''.join([os.getcwd(), '/0-old.zip'])
+ dest_path = ''.join([os.getcwd(), '/0.zip'])
+ test_target = divide_and_compress.DirectoryZipper(
+ ''.join([os.getcwd(), '/']), 'dummy', 1024*1024, True)
+ self.my_mox.StubOutWithMock(test_target, 'OpenZipFileAtPath')
+ test_target.OpenZipFileAtPath(source_path, mode='r').AndReturn(source)
+ test_target.OpenZipFileAtPath(dest_path,
+ compress=zipfile.ZIP_DEFLATED,
+ mode='w').AndReturn(dest)
+ self.my_mox.StubOutWithMock(os, 'rename')
+ os.rename(dest_path, source_path)
+ self.my_mox.StubOutWithMock(os, 'unlink')
+ os.unlink(source_path)
+
+ self.my_mox.ReplayAll()
+ test_target.RemoveLastFile()
+ self.my_mox.VerifyAll()
+
+ def CreateZipSource(self):
+ """Create a mock zip sourec object.
+
+ Read should only be called once, because the second file is the one
+ being removed.
+
+ Returns:
+ A configured mocked
+ """
+
+ source_zip = self.my_mox.CreateMock(ZipFile)
+ source_zip.infolist().AndReturn([self.files['file1'], self.files['file1']])
+ source_zip.infolist().AndReturn([self.files['file1'], self.files['file1']])
+ source_zip.read(self.files['file1'].filename).AndReturn(
+ self.files['file1'].contents)
+ source_zip.close()
+ return source_zip
+
+ def CreateZipDestination(self):
+ """Create mock destination zip.
+
+ Write should only be called once, because there are two files in the
+ source zip and we expect the second to be removed.
+
+ Returns:
+ A configured mocked
+ """
+
+ dest_zip = mox.MockObject(ZipFile)
+ dest_zip.writestr(self.files['file1'].filename,
+ self.files['file1'].contents)
+ dest_zip.close()
+ return dest_zip
+
+ def tearDown(self):
+ """Remove any stubs we've created."""
+ self.my_mox.UnsetStubs()
+
+
+class FixArchiveTests(unittest.TestCase):
+ """Tests for the DirectoryZipper.FixArchive method."""
+
+ def setUp(self):
+ """Create a mock file object."""
+ self.my_mox = mox.Mox()
+ self.file1 = BagOfParts()
+ self.file1.filename = 'file1.txt'
+ self.file1.contents = 'This is a test file'
+
+ def _InitMultiFileData(self):
+ """Create an array of mock file objects.
+
+ Create three mock file objects that we can use for testing.
+ """
+ self.multi_file_dir = []
+
+ file1 = BagOfParts()
+ file1.filename = 'file1.txt'
+ file1.contents = 'kjaskl;jkdjfkja;kjsnbvjnvnbuewklriujalvjsd'
+ self.multi_file_dir.append(file1)
+
+ file2 = BagOfParts()
+ file2.filename = 'file2.txt'
+ file2.contents = ('He entered the room and there in the center, it was.'
+ ' Looking upon the thing, suddenly he could not remember'
+ ' whether he had actually seen it before or whether'
+ ' his memory of it was merely the effect of something'
+ ' so often being imagined that it had long since become '
+ ' manifest in his mind.')
+ self.multi_file_dir.append(file2)
+
+ file3 = BagOfParts()
+ file3.filename = 'file3.txt'
+ file3.contents = 'Whoa, what is \'file2.txt\' all about?'
+ self.multi_file_dir.append(file3)
+
+ def testSingleFileArchive(self):
+ """Test behavior of FixArchive when the archive has a single member.
+
+ We expect that when this method is called with an archive that has a
+ single member that it will return False and unlink the archive.
+ """
+ test_target = divide_and_compress.DirectoryZipper(
+ ''.join([os.getcwd(), '/']), 'dummy', 1024*1024, True)
+ self.my_mox.StubOutWithMock(test_target, 'OpenZipFileAtPath')
+ test_target.OpenZipFileAtPath(
+ ''.join([os.getcwd(), '/0.zip']), mode='r').AndReturn(
+ self.CreateSingleFileMock())
+ self.my_mox.StubOutWithMock(os, 'unlink')
+ os.unlink(''.join([os.getcwd(), '/0.zip']))
+ self.my_mox.ReplayAll()
+ self.assertEqual(False, test_target.FixArchive('SIZE'))
+ self.my_mox.VerifyAll()
+
+ def CreateSingleFileMock(self):
+ """Create a mock ZipFile object for testSingleFileArchive.
+
+ We just need it to return a single member infolist twice
+
+ Returns:
+ A configured mock object
+ """
+ mock_zip = self.my_mox.CreateMock(ZipFile)
+ mock_zip.infolist().AndReturn([self.file1])
+ mock_zip.infolist().AndReturn([self.file1])
+ mock_zip.close()
+ return mock_zip
+
+ def testMultiFileArchive(self):
+ """Test behavior of DirectoryZipper.FixArchive with a multi-file archive.
+
+ We expect that FixArchive will rename the old archive, adding '-old' before
+ '.zip', read all the members except the last one of '-old' into a new
+ archive with the same name as the original, and then unlink the '-old' copy
+ """
+ test_target = divide_and_compress.DirectoryZipper(
+ ''.join([os.getcwd(), '/']), 'dummy', 1024*1024, True)
+ self.my_mox.StubOutWithMock(test_target, 'OpenZipFileAtPath')
+ test_target.OpenZipFileAtPath(
+ ''.join([os.getcwd(), '/0.zip']), mode='r').AndReturn(
+ self.CreateMultiFileMock())
+ self.my_mox.StubOutWithMock(test_target, 'RemoveLastFile')
+ test_target.RemoveLastFile(''.join([os.getcwd(), '/0.zip']))
+ self.my_mox.StubOutWithMock(os, 'stat')
+ os.stat(''.join([os.getcwd(), '/0.zip'])).AndReturn([49302])
+ self.my_mox.StubOutWithMock(stat, 'ST_SIZE')
+ stat.ST_SIZE = 0
+ self.my_mox.ReplayAll()
+ self.assertEqual(True, test_target.FixArchive('SIZE'))
+ self.my_mox.VerifyAll()
+
+ def CreateMultiFileMock(self):
+ """Create mock ZipFile object for use with testMultiFileArchive.
+
+ The mock just needs to return the infolist mock that is prepared in
+ InitMultiFileData()
+
+ Returns:
+ A configured mock object
+ """
+ self._InitMultiFileData()
+ mock_zip = self.my_mox.CreateMock(ZipFile)
+ mock_zip.infolist().AndReturn(self.multi_file_dir)
+ mock_zip.close()
+ return mock_zip
+
+ def tearDown(self):
+ """Unset any mocks that we've created."""
+ self.my_mox.UnsetStubs()
+
+
+class AddFileToArchiveTest(unittest.TestCase):
+ """Test behavior of method to add a file to an archive."""
+
+ def setUp(self):
+ """Setup the arguments for the DirectoryZipper object."""
+ self.my_mox = mox.Mox()
+ self.output_dir = '%s/' % os.getcwd()
+ self.file_to_add = 'file.txt'
+ self.input_dir = '/foo/bar/baz/'
+
+ def testAddFileToArchive(self):
+ """Test the DirectoryZipper.AddFileToArchive method.
+
+ We are testing a pretty trivial method, we just expect it to look at the
+ file its adding, so that it possible can through out a warning.
+ """
+ test_target = divide_and_compress.DirectoryZipper(self.output_dir,
+ self.input_dir,
+ 1024*1024, True)
+ self.my_mox.StubOutWithMock(test_target, 'OpenZipFileAtPath')
+ archive_mock = self.CreateArchiveMock()
+ test_target.OpenZipFileAtPath(
+ ''.join([self.output_dir, '0.zip']),
+ compress=zipfile.ZIP_DEFLATED).AndReturn(archive_mock)
+ self.StubOutOsModule()
+ self.my_mox.ReplayAll()
+ test_target.AddFileToArchive(''.join([self.input_dir, self.file_to_add]),
+ zipfile.ZIP_DEFLATED)
+ self.my_mox.VerifyAll()
+
+ def StubOutOsModule(self):
+ """Create a mock for the os.path and os.stat objects.
+
+ Create a stub that will return the type (file or directory) and size of the
+ object that is to be added.
+ """
+ self.my_mox.StubOutWithMock(os.path, 'isfile')
+ os.path.isfile(''.join([self.input_dir, self.file_to_add])).AndReturn(True)
+ self.my_mox.StubOutWithMock(os, 'stat')
+ os.stat(''.join([self.input_dir, self.file_to_add])).AndReturn([39480])
+ self.my_mox.StubOutWithMock(stat, 'ST_SIZE')
+ stat.ST_SIZE = 0
+
+ def CreateArchiveMock(self):
+ """Create a mock ZipFile for use with testAddFileToArchive.
+
+ Just verify that write is called with the file we expect and that the
+ archive is closed after the file addition
+
+ Returns:
+ A configured mock object
+ """
+ archive_mock = self.my_mox.CreateMock(ZipFile)
+ archive_mock.write(''.join([self.input_dir, self.file_to_add]),
+ self.file_to_add)
+ archive_mock.close()
+ return archive_mock
+
+ def tearDown(self):
+ self.my_mox.UnsetStubs()
+
+
+class CompressDirectoryTest(unittest.TestCase):
+ """Test the master method of the class.
+
+ Testing with the following directory structure.
+ /dir1/
+ /dir1/file1.txt
+ /dir1/file2.txt
+ /dir1/dir2/
+ /dir1/dir2/dir3/
+ /dir1/dir2/dir4/
+ /dir1/dir2/dir4/file3.txt
+ /dir1/dir5/
+ /dir1/dir5/file4.txt
+ /dir1/dir5/file5.txt
+ /dir1/dir5/file6.txt
+ /dir1/dir5/file7.txt
+ /dir1/dir6/
+ /dir1/dir6/file8.txt
+
+ file1.txt., file2.txt, file3.txt should be in 0.zip
+ file4.txt should be in 1.zip
+ file5.txt, file6.txt should be in 2.zip
+ file7.txt will not be stored since it will be too large compressed
+ file8.txt should b in 3.zip
+ """
+
+ def setUp(self):
+ """Setup all the mocks for this test."""
+ self.my_mox = mox.Mox()
+
+ self.base_dir = '/dir1'
+ self.output_path = '/out_dir/'
+ self.test_target = divide_and_compress.DirectoryZipper(
+ self.output_path, self.base_dir, 1024*1024, True)
+
+ self.InitArgLists()
+ self.InitOsDotPath()
+ self.InitArchiveIsValid()
+ self.InitWriteIndexRecord()
+ self.InitAddFileToArchive()
+
+ def tearDown(self):
+ self.my_mox.UnsetStubs()
+
+ def testCompressDirectory(self):
+ """Test the DirectoryZipper.CompressDirectory method."""
+ self.my_mox.ReplayAll()
+ for arguments in self.argument_lists:
+ self.test_target.CompressDirectory(None, arguments[0], arguments[1])
+ self.my_mox.VerifyAll()
+
+ def InitAddFileToArchive(self):
+ """Setup mock for DirectoryZipper.AddFileToArchive.
+
+ Make sure that the files are added in the order we expect.
+ """
+ self.my_mox.StubOutWithMock(self.test_target, 'AddFileToArchive')
+ self.test_target.AddFileToArchive('/dir1/file1.txt', zipfile.ZIP_DEFLATED)
+ self.test_target.AddFileToArchive('/dir1/file2.txt', zipfile.ZIP_DEFLATED)
+ self.test_target.AddFileToArchive('/dir1/dir2/dir4/file3.txt',
+ zipfile.ZIP_DEFLATED)
+ self.test_target.AddFileToArchive('/dir1/dir5/file4.txt',
+ zipfile.ZIP_DEFLATED)
+ self.test_target.AddFileToArchive('/dir1/dir5/file4.txt',
+ zipfile.ZIP_DEFLATED)
+ self.test_target.AddFileToArchive('/dir1/dir5/file5.txt',
+ zipfile.ZIP_DEFLATED)
+ self.test_target.AddFileToArchive('/dir1/dir5/file5.txt',
+ zipfile.ZIP_DEFLATED)
+ self.test_target.AddFileToArchive('/dir1/dir5/file6.txt',
+ zipfile.ZIP_DEFLATED)
+ self.test_target.AddFileToArchive('/dir1/dir5/file7.txt',
+ zipfile.ZIP_DEFLATED)
+ self.test_target.AddFileToArchive('/dir1/dir5/file7.txt',
+ zipfile.ZIP_DEFLATED)
+ self.test_target.AddFileToArchive('/dir1/dir6/file8.txt',
+ zipfile.ZIP_DEFLATED)
+
+ def InitWriteIndexRecord(self):
+ """Setup mock for DirectoryZipper.WriteIndexRecord."""
+ self.my_mox.StubOutWithMock(self.test_target, 'WriteIndexRecord')
+
+ # we are trying to compress 8 files, but we should only attempt to
+ # write an index record 7 times, because one file is too large to be stored
+ self.test_target.WriteIndexRecord().AndReturn(True)
+ self.test_target.WriteIndexRecord().AndReturn(False)
+ self.test_target.WriteIndexRecord().AndReturn(False)
+ self.test_target.WriteIndexRecord().AndReturn(True)
+ self.test_target.WriteIndexRecord().AndReturn(True)
+ self.test_target.WriteIndexRecord().AndReturn(False)
+ self.test_target.WriteIndexRecord().AndReturn(True)
+
+ def InitArchiveIsValid(self):
+ """Mock out DirectoryZipper.ArchiveIsValid and DirectoryZipper.FixArchive.
+
+ Mock these methods out such that file1, file2, and file3 go into one
+ archive. file4 then goes into the next archive, file5 and file6 in the
+ next, file 7 should appear too large to compress into an archive, and
+ file8 goes into the final archive
+ """
+ self.my_mox.StubOutWithMock(self.test_target, 'ArchiveIsValid')
+ self.my_mox.StubOutWithMock(self.test_target, 'FixArchive')
+ self.test_target.ArchiveIsValid().AndReturn(True)
+ self.test_target.ArchiveIsValid().AndReturn(True)
+ self.test_target.ArchiveIsValid().AndReturn(True)
+
+ # should be file4.txt
+ self.test_target.ArchiveIsValid().AndReturn(False)
+ self.test_target.FixArchive('SIZE').AndReturn(True)
+ self.test_target.ArchiveIsValid().AndReturn(True)
+
+ # should be file5.txt
+ self.test_target.ArchiveIsValid().AndReturn(False)
+ self.test_target.FixArchive('SIZE').AndReturn(True)
+ self.test_target.ArchiveIsValid().AndReturn(True)
+ self.test_target.ArchiveIsValid().AndReturn(True)
+
+ # should be file7.txt
+ self.test_target.ArchiveIsValid().AndReturn(False)
+ self.test_target.FixArchive('SIZE').AndReturn(True)
+ self.test_target.ArchiveIsValid().AndReturn(False)
+ self.test_target.FixArchive('SIZE').AndReturn(False)
+ self.test_target.ArchiveIsValid().AndReturn(True)
+
+ def InitOsDotPath(self):
+ """Mock out os.path.isfile.
+
+ Mock this out so the things we want to appear as files appear as files and
+ the things we want to appear as directories appear as directories. Also
+ make sure that the order of file visits is as we expect (which is why
+ InAnyOrder isn't used here).
+ """
+ self.my_mox.StubOutWithMock(os.path, 'isfile')
+ os.path.isfile('/dir1/dir2').AndReturn(False)
+ os.path.isfile('/dir1/dir5').AndReturn(False)
+ os.path.isfile('/dir1/dir6').AndReturn(False)
+ os.path.isfile('/dir1/file1.txt').AndReturn(True)
+ os.path.isfile('/dir1/file2.txt').AndReturn(True)
+ os.path.isfile('/dir1/dir2/dir3').AndReturn(False)
+ os.path.isfile('/dir1/dir2/dir4').AndReturn(False)
+ os.path.isfile('/dir1/dir2/dir4/file3.txt').AndReturn(True)
+ os.path.isfile('/dir1/dir5/file4.txt').AndReturn(True)
+ os.path.isfile('/dir1/dir5/file4.txt').AndReturn(True)
+ os.path.isfile('/dir1/dir5/file5.txt').AndReturn(True)
+ os.path.isfile('/dir1/dir5/file5.txt').AndReturn(True)
+ os.path.isfile('/dir1/dir5/file6.txt').AndReturn(True)
+ os.path.isfile('/dir1/dir5/file7.txt').AndReturn(True)
+ os.path.isfile('/dir1/dir5/file7.txt').AndReturn(True)
+ os.path.isfile('/dir1/dir6/file8.txt').AndReturn(True)
+
+ def InitArgLists(self):
+ """Create the directory path => directory contents mappings."""
+ self.argument_lists = []
+ self.argument_lists.append(['/dir1',
+ ['file1.txt', 'file2.txt', 'dir2', 'dir5',
+ 'dir6']])
+ self.argument_lists.append(['/dir1/dir2', ['dir3', 'dir4']])
+ self.argument_lists.append(['/dir1/dir2/dir3', []])
+ self.argument_lists.append(['/dir1/dir2/dir4', ['file3.txt']])
+ self.argument_lists.append(['/dir1/dir5',
+ ['file4.txt', 'file5.txt', 'file6.txt',
+ 'file7.txt']])
+ self.argument_lists.append(['/dir1/dir6', ['file8.txt']])
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tools/sdkmanager/Android.mk b/tools/sdkmanager/Android.mk
new file mode 100644
index 0000000..30df7f1
--- /dev/null
+++ b/tools/sdkmanager/Android.mk
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+SDKMANAGER_LOCAL_DIR := $(call my-dir)
+include $(SDKMANAGER_LOCAL_DIR)/app/Android.mk
+include $(SDKMANAGER_LOCAL_DIR)/libs/Android.mk
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/MODULE_LICENSE_EPL b/tools/sdkmanager/MODULE_LICENSE_APACHE2
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/MODULE_LICENSE_EPL
rename to tools/sdkmanager/MODULE_LICENSE_APACHE2
diff --git a/tools/sdkmanager/app/.classpath b/tools/sdkmanager/app/.classpath
new file mode 100644
index 0000000..45c59d3
--- /dev/null
+++ b/tools/sdkmanager/app/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/SdkLib"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/AndroidPrefs"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/SdkUiLib"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/tools/eclipse/features/com.android.ide.eclipse.editors/.project b/tools/sdkmanager/app/.project
similarity index 65%
copy from tools/eclipse/features/com.android.ide.eclipse.editors/.project
copy to tools/sdkmanager/app/.project
index a960976..e12c17d 100644
--- a/tools/eclipse/features/com.android.ide.eclipse.editors/.project
+++ b/tools/sdkmanager/app/.project
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
- <name>editors-feature</name>
+ <name>SdkManager</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
- <name>org.eclipse.pde.FeatureBuilder</name>
+ <name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
- <nature>org.eclipse.pde.FeatureNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
diff --git a/tools/sdkmanager/app/Android.mk b/tools/sdkmanager/app/Android.mk
new file mode 100644
index 0000000..24ba61f
--- /dev/null
+++ b/tools/sdkmanager/app/Android.mk
@@ -0,0 +1,5 @@
+# Copyright 2007 The Android Open Source Project
+#
+SDKMANAGERAPP_LOCAL_DIR := $(call my-dir)
+include $(SDKMANAGERAPP_LOCAL_DIR)/etc/Android.mk
+include $(SDKMANAGERAPP_LOCAL_DIR)/src/Android.mk
diff --git a/tools/sdkmanager/app/etc/Android.mk b/tools/sdkmanager/app/etc/Android.mk
new file mode 100644
index 0000000..8723cd8
--- /dev/null
+++ b/tools/sdkmanager/app/etc/Android.mk
@@ -0,0 +1,8 @@
+# Copyright 2008 The Android Open Source Project
+#
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_PREBUILT_EXECUTABLES := android
+include $(BUILD_HOST_PREBUILT)
+
diff --git a/tools/sdkmanager/app/etc/android b/tools/sdkmanager/app/etc/android
new file mode 100755
index 0000000..af4042b
--- /dev/null
+++ b/tools/sdkmanager/app/etc/android
@@ -0,0 +1,84 @@
+#!/bin/sh
+# Copyright 2005-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.
+
+# Set up prog to be the path of this script, including following symlinks,
+# and set up progdir to be the fully-qualified pathname of its directory.
+prog="$0"
+while [ -h "${prog}" ]; do
+ newProg=`/bin/ls -ld "${prog}"`
+ newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
+ if expr "x${newProg}" : 'x/' >/dev/null; then
+ prog="${newProg}"
+ else
+ progdir=`dirname "${prog}"`
+ prog="${progdir}/${newProg}"
+ fi
+done
+oldwd=`pwd`
+progdir=`dirname "${prog}"`
+cd "${progdir}"
+progdir=`pwd`
+prog="${progdir}"/`basename "${prog}"`
+cd "${oldwd}"
+
+jarfile=sdkmanager.jar
+frameworkdir="$progdir"
+libdir="$progdir"
+if [ ! -r "$frameworkdir/$jarfile" ]
+then
+ frameworkdir=`dirname "$progdir"`/tools/lib
+ libdir=`dirname "$progdir"`/tools/lib
+fi
+if [ ! -r "$frameworkdir/$jarfile" ]
+then
+ frameworkdir=`dirname "$progdir"`/framework
+ libdir=`dirname "$progdir"`/lib
+fi
+if [ ! -r "$frameworkdir/$jarfile" ]
+then
+ echo `basename "$prog"`": can't find $jarfile"
+ exit 1
+fi
+
+
+# Check args.
+if [ debug = "$1" ]; then
+ # add this in for debugging
+ java_debug=-agentlib:jdwp=transport=dt_socket,server=y,address=8050,suspend=y
+ shift 1
+else
+ java_debug=
+fi
+
+# Mac OS X needs an additional arg, or you get an "illegal thread" complaint.
+if [ `uname` = "Darwin" ]; then
+ os_opts="-XstartOnFirstThread"
+ #because Java 1.6 is 64 bits only and SWT doesn't support this, we force the usage of java 1.5
+ java_cmd="/System/Library/Frameworks/JavaVM.framework/Versions/1.5/Commands/java"
+else
+ os_opts=
+ java_cmd="java"
+fi
+
+if [ "$OSTYPE" = "cygwin" ] ; then
+ jarpath=`cygpath -w "$frameworkdir/$jarfile"`
+ progdir=`cygpath -w "$progdir"`
+else
+ jarpath="$frameworkdir/$jarfile"
+fi
+
+# need to use "java.ext.dirs" because "-jar" causes classpath to be ignored
+# might need more memory, e.g. -Xmx128M
+exec "$java_cmd" -Xmx256M $os_opts $java_debug -Djava.ext.dirs="$frameworkdir" -Djava.library.path="$libdir" -Dcom.android.sdkmanager.toolsdir="$progdir" -jar "$jarpath" "$@"
diff --git a/tools/sdkmanager/app/etc/android.bat b/tools/sdkmanager/app/etc/android.bat
new file mode 100755
index 0000000..2aa458d
--- /dev/null
+++ b/tools/sdkmanager/app/etc/android.bat
@@ -0,0 +1,48 @@
+@echo off
+rem Copyright (C) 2007 The Android Open Source Project
+rem
+rem Licensed under the Apache License, Version 2.0 (the "License");
+rem you may not use this file except in compliance with the License.
+rem You may obtain a copy of the License at
+rem
+rem http://www.apache.org/licenses/LICENSE-2.0
+rem
+rem Unless required by applicable law or agreed to in writing, software
+rem distributed under the License is distributed on an "AS IS" BASIS,
+rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+rem See the License for the specific language governing permissions and
+rem limitations under the License.
+
+rem don't modify the caller's environment
+setlocal
+
+rem Set up prog to be the path of this script, including following symlinks,
+rem and set up progdir to be the fully-qualified pathname of its directory.
+set prog=%~f0
+
+rem Change current directory to where ddms is, to avoid issues with directories
+rem containing whitespaces.
+cd %~dp0
+
+set jarfile=sdkmanager.jar
+set frameworkdir=
+set libdir=
+
+if exist %frameworkdir%%jarfile% goto JarFileOk
+ set frameworkdir=lib\
+ set libdir=lib\
+
+if exist %frameworkdir%%jarfile% goto JarFileOk
+ set frameworkdir=..\framework\
+ set libdir=..\lib\
+
+:JarFileOk
+
+if debug NEQ "%1" goto NoDebug
+ set java_debug=-agentlib:jdwp=transport=dt_socket,server=y,address=8050,suspend=y
+ shift 1
+:NoDebug
+
+set jarpath=%frameworkdir%%jarfile%
+
+call java %java_debug% -Djava.ext.dirs=%frameworkdir% -Djava.library.path=%libdir% -Dcom.android.sdkmanager.toolsdir= -jar %jarpath% %*
diff --git a/tools/sdkmanager/app/etc/manifest.txt b/tools/sdkmanager/app/etc/manifest.txt
new file mode 100644
index 0000000..5676634
--- /dev/null
+++ b/tools/sdkmanager/app/etc/manifest.txt
@@ -0,0 +1 @@
+Main-Class: com.android.sdkmanager.Main
diff --git a/tools/sdkmanager/app/src/Android.mk b/tools/sdkmanager/app/src/Android.mk
new file mode 100644
index 0000000..b508076
--- /dev/null
+++ b/tools/sdkmanager/app/src/Android.mk
@@ -0,0 +1,16 @@
+# Copyright 2007 The Android Open Source Project
+#
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_JAR_MANIFEST := ../etc/manifest.txt
+LOCAL_JAVA_LIBRARIES := \
+ androidprefs \
+ sdklib \
+ sdkuilib
+LOCAL_MODULE := sdkmanager
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
diff --git a/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java b/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java
new file mode 100644
index 0000000..72bd2aa
--- /dev/null
+++ b/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java
@@ -0,0 +1,487 @@
+/*
+ * 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.sdkmanager;
+
+import com.android.prefs.AndroidLocation;
+import com.android.prefs.AndroidLocation.AndroidLocationException;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.ISdkLog;
+import com.android.sdklib.SdkConstants;
+import com.android.sdklib.SdkManager;
+import com.android.sdklib.IAndroidTarget.IOptionalLibrary;
+import com.android.sdklib.vm.HardwareProperties;
+import com.android.sdklib.vm.VmManager;
+import com.android.sdklib.vm.HardwareProperties.HardwareProperty;
+import com.android.sdklib.vm.VmManager.VmInfo;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Main class for the 'android' application
+ *
+ */
+class Main {
+
+ private final static String TOOLSDIR = "com.android.sdkmanager.toolsdir";
+
+ private final static String ARG_LIST_TARGET = "target";
+ private final static String ARG_LIST_VM = "vm";
+
+ private final static String[] BOOLEAN_YES_REPLIES = new String[] { "yes", "y" };
+ private final static String[] BOOLEAN_NO_REPLIES = new String[] { "no", "n" };
+
+ private String mSdkFolder;
+ private SdkManager mSdkManager;
+ private VmManager mVmManager;
+
+ /* --list parameters */
+ private String mListObject;
+
+ /* --create parameters */
+ private boolean mCreateVm;
+ private int mCreateTargetId;
+ private IAndroidTarget mCreateTarget;
+ private String mCreateName;
+
+ public static void main(String[] args) {
+ new Main().run(args);
+ }
+
+ /**
+ * Runs the sdk manager app
+ * @param args
+ */
+ private void run(String[] args) {
+ init();
+ parseArgs(args);
+ parseSdk();
+ doAction();
+ }
+
+ /**
+ * Init the application by making sure the SDK path is available and
+ * doing basic parsing of the SDK.
+ */
+ private void init() {
+ /* We get passed a property for the tools dir */
+ String toolsDirProp = System.getProperty(TOOLSDIR);
+ if (toolsDirProp == null) {
+ // for debugging, it's easier to override using the process environment
+ toolsDirProp = System.getenv(TOOLSDIR);
+ }
+ if (toolsDirProp == null) {
+ printHelpAndExit("ERROR: The tools directory property is not set, please make sure you are executing android or android.bat");
+ }
+
+ // got back a level for the SDK folder
+ File tools = new File(toolsDirProp);
+ mSdkFolder = tools.getParent();
+
+ }
+
+ /**
+ * Parses command-line arguments, or prints help/usage and exits if error.
+ * @param args arguments passed to the program
+ */
+ private void parseArgs(String[] args) {
+ final int numArgs = args.length;
+
+ try {
+ int argPos = 0;
+ for (; argPos < numArgs; argPos++) {
+ final String arg = args[argPos];
+ if (arg.equals("-l") || arg.equals("--list")) {
+ mListObject = args[++argPos];
+ } else if (arg.equals("-c") || arg.equals("--create")) {
+ mCreateVm = true;
+ parseCreateArgs(args, ++argPos);
+ }
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ /* Any OOB triggers help */
+ printHelpAndExit("ERROR: Not enough arguments.");
+ }
+ }
+
+ private void parseCreateArgs(String[] args, int argPos) {
+ final int numArgs = args.length;
+
+ try {
+ for (; argPos < numArgs; argPos++) {
+ final String arg = args[argPos];
+ if (arg.equals("-t") || arg.equals("--target")) {
+ String targetId = args[++argPos];
+ try {
+ // get the target id
+ mCreateTargetId = Integer.parseInt(targetId);
+ } catch (NumberFormatException e) {
+ printHelpAndExit("ERROR: Target Id is not a number");
+ }
+ } else if (arg.equals("-n") || arg.equals("--name")) {
+ mCreateName = args[++argPos];
+ } else {
+ printHelpAndExit("ERROR: '%s' unknown argument for --create mode",
+ args[argPos]);
+ }
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ /* Any OOB triggers help */
+ printHelpAndExit("ERROR: Not enough arguments for --create");
+ }
+ }
+
+ /**
+ * Does the basic SDK parsing required for all actions
+ */
+ private void parseSdk() {
+ mSdkManager = SdkManager.createManager(mSdkFolder, new ISdkLog() {
+ public void error(String errorFormat, Object... args) {
+ System.err.printf("Error: " + errorFormat, args);
+ System.err.println("");
+ }
+
+ public void warning(String warningFormat, Object... args) {
+ if (false) {
+ // TODO: on display warnings in verbose mode.
+ System.out.printf("Warning: " + warningFormat, args);
+ System.out.println("");
+ }
+ }
+ });
+
+ if (mSdkManager == null) {
+ printHelpAndExit("ERROR: Unable to parse SDK content.");
+ }
+ }
+
+ /**
+ * Actually do an action...
+ */
+ private void doAction() {
+ if (mListObject != null) {
+ // list action.
+ if (ARG_LIST_TARGET.equals(mListObject)) {
+ displayTargetList();
+ } else if (ARG_LIST_VM.equals(mListObject)) {
+ displayVmList();
+ } else {
+ printHelpAndExit("'%s' is not a valid --list option", mListObject);
+ }
+ } else if (mCreateVm) {
+ createVm();
+ } else {
+ printHelpAndExit(null);
+ }
+ }
+
+ /**
+ * Displays the list of available Targets (Platforms and Add-ons)
+ */
+ private void displayTargetList() {
+ System.out.println("Available Android targets:");
+
+ int index = 1;
+ for (IAndroidTarget target : mSdkManager.getTargets()) {
+ if (target.isPlatform()) {
+ System.out.printf("[%d] %s\n", index, target.getName());
+ System.out.printf(" API level: %d\n", target.getApiVersionNumber());
+ } else {
+ System.out.printf("[%d] Add-on: %s\n", index, target.getName());
+ System.out.printf(" Vendor: %s\n", target.getVendor());
+ if (target.getDescription() != null) {
+ System.out.printf(" Description: %s\n", target.getDescription());
+ }
+ System.out.printf(" Based on Android %s (API level %d)\n",
+ target.getApiVersionName(), target.getApiVersionNumber());
+
+ // display the optional libraries.
+ IOptionalLibrary[] libraries = target.getOptionalLibraries();
+ if (libraries != null) {
+ for (IOptionalLibrary library : libraries) {
+ System.out.printf(" Library: %s (%s)\n", library.getName(),
+ library.getJarName());
+ }
+ }
+ }
+
+ // get the target skins
+ String[] skins = target.getSkins();
+ System.out.print(" Skins: ");
+ if (skins != null) {
+ boolean first = true;
+ for (String skin : skins) {
+ if (first == false) {
+ System.out.print(", ");
+ } else {
+ first = false;
+ }
+ System.out.print(skin);
+ }
+ System.out.println("");
+ } else {
+ System.out.println("no skins.");
+ }
+
+ index++;
+ }
+ }
+
+ /**
+ * Displays the list of available VMs.
+ */
+ private void displayVmList() {
+ try {
+ mVmManager = new VmManager(mSdkManager, null /* sdklog */);
+
+ System.out.println("Available Android VMs:");
+
+ int index = 1;
+ for (VmInfo info : mVmManager.getVms()) {
+ System.out.printf("[%d] %s\n", index, info.getName());
+ System.out.printf(" Path: %s\n", info.getPath());
+
+ // get the target of the Vm
+ IAndroidTarget target = info.getTarget();
+ if (target.isPlatform()) {
+ System.out.printf(" Target: %s (API level %d)\n", target.getName(),
+ target.getApiVersionNumber());
+ } else {
+ System.out.printf(" Target: %s (%s)\n", target.getName(), target
+ .getVendor());
+ System.out.printf(" Based on Android %s (API level %d)\n", target
+ .getApiVersionName(), target.getApiVersionNumber());
+
+ }
+
+ index++;
+ }
+ } catch (AndroidLocationException e) {
+ printHelpAndExit(e.getMessage());
+ }
+ }
+
+ /**
+ * Creates a new VM. This is a text based creation with command line prompt.
+ */
+ private void createVm() {
+ // find a matching target
+ if (mCreateTargetId >= 1 && mCreateTargetId <= mSdkManager.getTargets().length) {
+ mCreateTarget = mSdkManager.getTargets()[mCreateTargetId-1]; // target it is 1-based
+ } else {
+ printHelpAndExit(
+ "ERROR: Target Id is not a valid Id. Check android --list target for the list of targets.");
+ }
+
+ try {
+ // default to standard path now
+ String vmRoot = AndroidLocation.getFolder() + AndroidLocation.FOLDER_VMS;
+
+ Map<String, String> hardwareConfig = null;
+ if (mCreateTarget.isPlatform()) {
+ try {
+ hardwareConfig = promptForHardware(mCreateTarget);
+ } catch (IOException e) {
+ printHelpAndExit(e.getMessage());
+ }
+ }
+
+ VmManager.createVm(vmRoot, mCreateName, mCreateTarget, null /*skinName*/,
+ null /*sdcardPath*/, 0 /*sdcardSize*/, hardwareConfig,
+ null /* sdklog */);
+ } catch (AndroidLocationException e) {
+ printHelpAndExit(e.getMessage());
+ }
+ }
+
+ /**
+ * Prompts the user to setup a hardware config for a Platform-based VM.
+ * @throws IOException
+ */
+ private Map<String, String> promptForHardware(IAndroidTarget createTarget) throws IOException {
+ byte[] readLineBuffer = new byte[256];
+ String result;
+ String defaultAnswer = "no";
+
+ System.out.print(String.format("%s is a basic Android platform.\n",
+ createTarget.getName()));
+ System.out.print(String.format("Do you which to create a custom hardware profile [%s]",
+ defaultAnswer));
+
+ result = readLine(readLineBuffer);
+ // handle default:
+ if (result.length() == 0) {
+ result = defaultAnswer;
+ }
+
+ if (getBooleanReply(result) == false) {
+ // no custom config.
+ return null;
+ }
+
+ System.out.println(""); // empty line
+
+ // get the list of possible hardware properties
+ File hardwareDefs = new File (mSdkFolder + File.separator +
+ SdkConstants.OS_SDK_TOOLS_LIB_FOLDER, SdkConstants.FN_HARDWARE_INI);
+ List<HardwareProperty> list = HardwareProperties.parseHardwareDefinitions(hardwareDefs,
+ null /*sdkLog*/);
+
+ HashMap<String, String> map = new HashMap<String, String>();
+
+ for (int i = 0 ; i < list.size() ;) {
+ HardwareProperty property = list.get(i);
+
+ String description = property.getDescription();
+ if (description != null) {
+ System.out.printf("%s: %s\n", property.getAbstract(), description);
+ } else {
+ System.out.println(property.getAbstract());
+ }
+
+ String defaultValue = property.getDefault();
+
+ if (defaultValue != null) {
+ System.out.printf("%s [%s]:", property.getName(), defaultValue);
+ } else {
+ System.out.printf("%s (%s):", property.getName(), property.getType());
+ }
+
+ result = readLine(readLineBuffer);
+ if (result.length() == 0) {
+ if (defaultValue != null) {
+ System.out.println(""); // empty line
+ i++; // go to the next property if we have a valid default value.
+ // if there's no default, we'll redo this property
+ }
+ continue;
+ }
+
+ switch (property.getType()) {
+ case BOOLEAN:
+ try {
+ if (getBooleanReply(result)) {
+ map.put(property.getName(), "yes");
+ i++; // valid reply, move to next property
+ } else {
+ map.put(property.getName(), "no");
+ i++; // valid reply, move to next property
+ }
+ } catch (IOException e) {
+ // display error, and do not increment i to redo this property
+ System.out.println("\n" + e.getMessage());
+ }
+ break;
+ case INTEGER:
+ try {
+ @SuppressWarnings("unused")
+ int value = Integer.parseInt(result);
+ map.put(property.getName(), result);
+ i++; // valid reply, move to next property
+ } catch (NumberFormatException e) {
+ // display error, and do not increment i to redo this property
+ System.out.println("\n" + e.getMessage());
+ }
+ break;
+ case DISKSIZE:
+ // TODO check validity
+ map.put(property.getName(), result);
+ i++; // valid reply, move to next property
+ break;
+ }
+
+ System.out.println(""); // empty line
+ }
+
+ return map;
+ }
+
+ /**
+ * Read the line from the input stream.
+ * @param buffer
+ * @return
+ * @throws IOException
+ */
+ private String readLine(byte[] buffer) throws IOException {
+ int count = System.in.read(buffer);
+
+ // is the input longer than the buffer?
+ if (count == buffer.length && buffer[count-1] != 10) {
+ // create a new temp buffer
+ byte[] tempBuffer = new byte[256];
+
+ // and read the rest
+ String secondHalf = readLine(tempBuffer);
+
+ // return a concat of both
+ return new String(buffer, 0, count) + secondHalf;
+ }
+
+ return new String(buffer, 0, count - 1); // -1 to not include the carriage return
+ }
+
+ /**
+ * Returns the boolean value represented by the string.
+ * @throws IOException If the value is not a boolean string.
+ */
+ private boolean getBooleanReply(String reply) throws IOException {
+ for (String valid : BOOLEAN_YES_REPLIES) {
+ if (valid.equalsIgnoreCase(reply)) {
+ return true;
+ }
+ }
+
+ for (String valid : BOOLEAN_NO_REPLIES) {
+ if (valid.equalsIgnoreCase(reply)) {
+ return false;
+ }
+ }
+
+ throw new IOException(String.format("%s is not a valid reply", reply));
+ }
+
+ /**
+ * Prints the help/usage and exits.
+ * @param errorFormat Optional error message to print prior to usage using String.format
+ * @param args Arguments for String.format
+ */
+ private void printHelpAndExit(String errorFormat, Object... args) {
+ if (errorFormat != null) {
+ System.err.println(String.format(errorFormat, args));
+ }
+
+ /*
+ * usage should fit in 80 columns
+ * 12345678901234567890123456789012345678901234567890123456789012345678901234567890
+ */
+ final String usage = "\n" +
+ "Usage:\n" +
+ " android --list [target|vm]\n" +
+ " android --create --target <target id> --name <name>\n" +
+ "\n" +
+ "Options:\n" +
+ " -l [target|vm], --list [target|vm]\n" +
+ " Outputs the available targets or Virtual Machines and their Ids.\n" +
+ "\n";
+
+ System.out.println(usage);
+ System.exit(1);
+ }
+}
\ No newline at end of file
diff --git a/tools/sdkmanager/libs/Android.mk b/tools/sdkmanager/libs/Android.mk
new file mode 100644
index 0000000..a934aa7
--- /dev/null
+++ b/tools/sdkmanager/libs/Android.mk
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+SDKLIBS_LOCAL_DIR := $(call my-dir)
+include $(SDKLIBS_LOCAL_DIR)/sdklib/Android.mk
+include $(SDKLIBS_LOCAL_DIR)/sdkuilib/Android.mk
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/.classpath b/tools/sdkmanager/libs/sdklib/.classpath
similarity index 74%
rename from tools/eclipse/plugins/com.android.ide.eclipse.platform/.classpath
rename to tools/sdkmanager/libs/sdklib/.classpath
index 751c8f2..fc17a43 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/.classpath
+++ b/tools/sdkmanager/libs/sdklib/.classpath
@@ -2,6 +2,6 @@
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/AndroidPrefs"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/tools/eclipse/features/com.android.ide.eclipse.editors/.project b/tools/sdkmanager/libs/sdklib/.project
similarity index 65%
rename from tools/eclipse/features/com.android.ide.eclipse.editors/.project
rename to tools/sdkmanager/libs/sdklib/.project
index a960976..97a8578 100644
--- a/tools/eclipse/features/com.android.ide.eclipse.editors/.project
+++ b/tools/sdkmanager/libs/sdklib/.project
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
- <name>editors-feature</name>
+ <name>SdkLib</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
- <name>org.eclipse.pde.FeatureBuilder</name>
+ <name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
- <nature>org.eclipse.pde.FeatureNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
diff --git a/tools/sdkmanager/libs/sdklib/Android.mk b/tools/sdkmanager/libs/sdklib/Android.mk
new file mode 100644
index 0000000..509c573
--- /dev/null
+++ b/tools/sdkmanager/libs/sdklib/Android.mk
@@ -0,0 +1,17 @@
+#
+# 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.
+#
+SDKLIB_LOCAL_DIR := $(call my-dir)
+include $(SDKLIB_LOCAL_DIR)/src/Android.mk
diff --git a/tools/sdkmanager/libs/sdklib/src/Android.mk b/tools/sdkmanager/libs/sdklib/src/Android.mk
new file mode 100644
index 0000000..a059a46
--- /dev/null
+++ b/tools/sdkmanager/libs/sdklib/src/Android.mk
@@ -0,0 +1,27 @@
+#
+# 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.
+#
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_JAVA_LIBRARIES := \
+ androidprefs
+
+LOCAL_MODULE := sdklib
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java
new file mode 100644
index 0000000..5759613
--- /dev/null
+++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java
@@ -0,0 +1,198 @@
+/*
+ * 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.sdklib;
+
+import java.io.File;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * Represents an add-on target in the SDK.
+ * An add-on extends a standard {@link PlatformTarget}.
+ */
+final class AddOnTarget implements IAndroidTarget {
+ /**
+ * String to compute hash for add-on targets.
+ * Format is vendor:name:apiVersion
+ * */
+ private final static String ADD_ON_FORMAT = "%s:%s:%d"; //$NON-NLS-1$
+
+ private final static class OptionalLibrary implements IOptionalLibrary {
+ private final String mJarName;
+ private final String mJarPath;
+ private final String mName;
+
+ OptionalLibrary(String jarName, String jarPath, String name) {
+ mJarName = jarName;
+ mJarPath = jarPath;
+ mName = name;
+ }
+
+ public String getJarName() {
+ return mJarName;
+ }
+
+ public String getJarPath() {
+ return mJarPath;
+ }
+
+ public String getName() {
+ return mName;
+ }
+ }
+
+ private final String mLocation;
+ private final PlatformTarget mBasePlatform;
+ private final String mName;
+ private final String mVendor;
+ private final String mDescription;
+ private String[] mSkins;
+ private IOptionalLibrary[] mLibraries;
+
+ /**
+ * Creates a new add-on
+ * @param location the OS path location of the add-on
+ * @param name the name of the add-on
+ * @param vendor the vendor name of the add-on
+ * @param description the add-on description
+ * @param libMap A map containing the optional libraries. The map key is the fully-qualified
+ * library name. The value is the .jar filename
+ * @param basePlatform the platform the add-on is extending.
+ */
+ AddOnTarget(String location, String name, String vendor, String description,
+ Map<String, String> libMap, PlatformTarget basePlatform) {
+ if (location.endsWith(File.separator) == false) {
+ location = location + File.separator;
+ }
+
+ mLocation = location;
+ mName = name;
+ mVendor = vendor;
+ mDescription = description;
+ mBasePlatform = basePlatform;
+
+ // handle the optional libraries.
+ mLibraries = new IOptionalLibrary[libMap.size()];
+ int index = 0;
+ for (Entry<String, String> entry : libMap.entrySet()) {
+ mLibraries[index++] = new OptionalLibrary(entry.getValue(),
+ mLocation + SdkConstants.OS_ADDON_LIBS_FOLDER + entry.getValue(),
+ entry.getKey());
+ }
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public String getVendor() {
+ return mVendor;
+ }
+
+ public String getDescription() {
+ return mDescription;
+ }
+
+ public String getApiVersionName() {
+ // this is always defined by the base platform
+ return mBasePlatform.getApiVersionName();
+ }
+
+ public int getApiVersionNumber() {
+ // this is always defined by the base platform
+ return mBasePlatform.getApiVersionNumber();
+ }
+
+ public boolean isPlatform() {
+ return false;
+ }
+
+ public String getPath(int pathId) {
+ switch (pathId) {
+ case IMAGES:
+ return mLocation + SdkConstants.OS_IMAGES_FOLDER;
+ case SKINS:
+ return mLocation + SdkConstants.OS_SKINS_FOLDER;
+ default :
+ return mBasePlatform.getPath(pathId);
+ }
+ }
+
+ public String[] getSkins() {
+ return mSkins;
+ }
+
+ public IOptionalLibrary[] getOptionalLibraries() {
+ return mLibraries;
+ }
+
+ public String hashString() {
+ return String.format(ADD_ON_FORMAT, mVendor, mName, mBasePlatform.getApiVersionNumber());
+ }
+
+ @Override
+ public int hashCode() {
+ return hashString().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof AddOnTarget) {
+ AddOnTarget addon = (AddOnTarget)obj;
+
+ return mVendor.equals(addon.mVendor) && mName.equals(addon.mName) &&
+ mBasePlatform.getApiVersionNumber() == addon.mBasePlatform.getApiVersionNumber();
+ }
+
+ return super.equals(obj);
+ }
+
+ /*
+ * Always return +1 if the object we compare to is a platform.
+ * Otherwise, do vendor then name then api version comparison.
+ * (non-Javadoc)
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo(IAndroidTarget target) {
+ if (target.isPlatform()) {
+ return +1;
+ }
+
+ // vendor
+ int value = mVendor.compareTo(target.getVendor());
+
+ // name
+ if (value == 0) {
+ value = mName.compareTo(target.getName());
+ }
+
+ // api version
+ if (value == 0) {
+ value = getApiVersionNumber() - target.getApiVersionNumber();
+ }
+
+ return value;
+ }
+
+
+ // ---- local methods.
+
+
+ public void setSkins(String[] skins) {
+ mSkins = skins;
+ }
+}
diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/IAndroidTarget.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/IAndroidTarget.java
new file mode 100644
index 0000000..e5d45b2
--- /dev/null
+++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/IAndroidTarget.java
@@ -0,0 +1,104 @@
+/*
+ * 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.sdklib;
+
+
+/**
+ * A version of Android that application can target when building.
+ */
+public interface IAndroidTarget extends Comparable<IAndroidTarget> {
+
+ public static int ANDROID_JAR = 1;
+ public static int ANDROID_AIDL = 2;
+ public static int IMAGES = 3;
+ public static int SAMPLES = 4;
+ public static int SKINS = 5;
+ public static int TEMPLATES = 6;
+ public static int DATA = 7;
+ public static int ATTRIBUTES = 8;
+ public static int MANIFEST_ATTRIBUTES = 9;
+ public static int LAYOUT_LIB = 10;
+ public static int RESOURCES = 11;
+ public static int FONTS = 12;
+ public static int WIDGETS = 13;
+ public static int ACTIONS_ACTIVITY = 14;
+ public static int ACTIONS_BROADCAST = 15;
+ public static int ACTIONS_SERVICE = 16;
+ public static int CATEGORIES = 17;
+ public static int SOURCES = 18;
+
+ public interface IOptionalLibrary {
+ String getName();
+ String getJarName();
+ String getJarPath();
+ }
+
+ /**
+ * Returns the name of the vendor of the target.
+ */
+ String getVendor();
+
+ /**
+ * Returns the name of the target.
+ */
+ String getName();
+
+ /**
+ * Returns the description of the target.
+ */
+ String getDescription();
+
+ /**
+ * Returns the api version as an integer.
+ */
+ int getApiVersionNumber();
+
+ /**
+ * Returns the platform version as a readable string.
+ */
+ String getApiVersionName();
+
+ /**
+ * Returns true if the target is a standard Android platform.
+ */
+ boolean isPlatform();
+
+ /**
+ * Returns the path of a platform component.
+ * @param pathId the id representing the path to return. Any of the constants defined in the
+ * {@link ITargetDataProvider} interface can be used.
+ */
+ String getPath(int pathId);
+
+ /**
+ * Returns the available skins for this target.
+ */
+ String[] getSkins();
+
+ /**
+ * Returns the available optional libraries for this target.
+ * @return an array of optional libraries or <code>null</code> if there is none.
+ */
+ IOptionalLibrary[] getOptionalLibraries();
+
+ /**
+ * Returns a string able to uniquely identify a target.
+ * Typically the target will encode information such as api level, whether it's a platform
+ * or add-on, and if it's an add-on vendor and add-on name.
+ */
+ String hashString();
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/ISdkLog.java
similarity index 61%
copy from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java
copy to tools/sdkmanager/libs/sdklib/src/com/android/sdklib/ISdkLog.java
index 4c368d9..3eda37f 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java
+++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/ISdkLog.java
@@ -14,19 +14,12 @@
* limitations under the License.
*/
-
-package com.android.ide.eclipse.editors.uimodel;
+package com.android.sdklib;
/**
- * This interface decoration indicates that a given UiAttributeNode can both
- * set and get its current value.
+ * Interface used to display warnings/errors while parsing the SDK content.
*/
-public interface IUiSettableAttributeNode {
-
- /** Returns the current value of the node. */
- public String getCurrentValue();
-
- /** Sets the current value of the node. */
- public void setCurrentValue(String value);
-
+public interface ISdkLog {
+ void warning(String warningFormat, Object... args);
+ void error(String errorFormat, Object... args);
}
diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java
new file mode 100644
index 0000000..f5a1f6d
--- /dev/null
+++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java
@@ -0,0 +1,186 @@
+/*
+ * 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.sdklib;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Represents a platform target in the SDK.
+ */
+final class PlatformTarget implements IAndroidTarget {
+ /** String used to get a hash to the platform target */
+ private final static String PLATFORM_HASH = "android-%d";
+
+ private final static String PLATFORM_VENDOR = "Android";
+ private final static String PLATFORM_NAME = "Android %s";
+
+ private final String mLocation;
+ private final String mName;
+ private final int mApiVersionNumber;
+ private final String mApiVersionName;
+ private final Map<String, String> mProperties;
+ private final Map<Integer, String> mPaths = new HashMap<Integer, String>();
+ private String[] mSkins;
+
+ PlatformTarget(String location, Map<String, String> properties,
+ int apiNumber, String apiName) {
+ mName = String.format(PLATFORM_NAME, apiName);
+ if (location.endsWith(File.separator) == false) {
+ location = location + File.separator;
+ }
+ mLocation = location;
+ mProperties = Collections.unmodifiableMap(properties);
+ mApiVersionNumber = apiNumber;
+ mApiVersionName = apiName;
+
+ // pre-build the path to the platform components
+ mPaths.put(ANDROID_JAR, mLocation + SdkConstants.FN_FRAMEWORK_LIBRARY);
+ mPaths.put(SOURCES, mLocation + SdkConstants.FD_ANDROID_SOURCES);
+ mPaths.put(ANDROID_AIDL, mLocation + SdkConstants.FN_FRAMEWORK_AIDL);
+ mPaths.put(IMAGES, mLocation + SdkConstants.OS_IMAGES_FOLDER);
+ mPaths.put(SAMPLES, mLocation + SdkConstants.OS_PLATFORM_SAMPLES_FOLDER);
+ mPaths.put(SKINS, mLocation + SdkConstants.OS_SKINS_FOLDER);
+ mPaths.put(TEMPLATES, mLocation + SdkConstants.OS_PLATFORM_TEMPLATES_FOLDER);
+ mPaths.put(DATA, mLocation + SdkConstants.OS_PLATFORM_DATA_FOLDER);
+ mPaths.put(ATTRIBUTES, mLocation + SdkConstants.OS_PLATFORM_ATTRS_XML);
+ mPaths.put(MANIFEST_ATTRIBUTES, mLocation + SdkConstants.OS_PLATFORM_ATTRS_MANIFEST_XML);
+ mPaths.put(RESOURCES, mLocation + SdkConstants.OS_PLATFORM_RESOURCES_FOLDER);
+ mPaths.put(FONTS, mLocation + SdkConstants.OS_PLATFORM_FONTS_FOLDER);
+ mPaths.put(LAYOUT_LIB, mLocation + SdkConstants.OS_PLATFORM_DATA_FOLDER +
+ SdkConstants.FN_LAYOUTLIB_JAR);
+ mPaths.put(WIDGETS, mLocation + SdkConstants.OS_PLATFORM_DATA_FOLDER +
+ SdkConstants.FN_WIDGETS);
+ mPaths.put(ACTIONS_ACTIVITY, mLocation + SdkConstants.OS_PLATFORM_DATA_FOLDER +
+ SdkConstants.FN_INTENT_ACTIONS_ACTIVITY);
+ mPaths.put(ACTIONS_BROADCAST, mLocation + SdkConstants.OS_PLATFORM_DATA_FOLDER +
+ SdkConstants.FN_INTENT_ACTIONS_BROADCAST);
+ mPaths.put(ACTIONS_SERVICE, mLocation + SdkConstants.OS_PLATFORM_DATA_FOLDER +
+ SdkConstants.FN_INTENT_ACTIONS_SERVICE);
+ mPaths.put(CATEGORIES, mLocation + SdkConstants.OS_PLATFORM_DATA_FOLDER +
+ SdkConstants.FN_INTENT_CATEGORIES);
+ }
+
+ public String getLocation() {
+ return mLocation;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * For Platform, the vendor name is always "Android".
+ *
+ * @see com.android.sdklib.IAndroidTarget#getVendor()
+ */
+ public String getVendor() {
+ return PLATFORM_VENDOR;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * Description for the Android platform is dynamically generated.
+ *
+ * @see com.android.sdklib.IAndroidTarget#getDescription()
+ */
+ public String getDescription() {
+ return String.format("Standard Android platform %s", mApiVersionName);
+ }
+
+ public int getApiVersionNumber(){
+ return mApiVersionNumber;
+ }
+
+ public String getApiVersionName() {
+ return mApiVersionName;
+ }
+
+ public boolean isPlatform() {
+ return true;
+ }
+
+ public String getPath(int pathId) {
+ return mPaths.get(pathId);
+ }
+
+ public String[] getSkins() {
+ return mSkins;
+ }
+
+ /*
+ * Always returns null, as a standard platforms have no optional libraries.
+ *
+ * (non-Javadoc)
+ * @see com.android.sdklib.IAndroidTarget#getOptionalLibraries()
+ */
+ public IOptionalLibrary[] getOptionalLibraries() {
+ return null;
+ }
+
+
+ public String hashString() {
+ return String.format(PLATFORM_HASH, mApiVersionNumber);
+ }
+
+ @Override
+ public int hashCode() {
+ return hashString().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof PlatformTarget) {
+ return mApiVersionNumber == ((PlatformTarget)obj).mApiVersionNumber;
+ }
+
+ return super.equals(obj);
+ }
+
+ /*
+ * Always return -1 if the object we compare to is an addon.
+ * Otherwise, compare api level.
+ * (non-Javadoc)
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo(IAndroidTarget target) {
+ if (target.isPlatform() == false) {
+ return -1;
+ }
+
+ return mApiVersionNumber - target.getApiVersionNumber();
+ }
+
+ // ---- platform only methods.
+
+ public String getProperty(String name) {
+ return mProperties.get(name);
+ }
+
+ public Map<String, String> getProperties() {
+ return mProperties; // mProperties is unmodifiable.
+ }
+
+ void setSkins(String[] skins) {
+ mSkins = skins;
+ }
+}
diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
new file mode 100644
index 0000000..78d1fda
--- /dev/null
+++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
@@ -0,0 +1,174 @@
+/*
+ * 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.sdklib;
+
+import java.io.File;
+
+/**
+ * Constant definition class.<br>
+ * <br>
+ * Most constants have a prefix defining the content.
+ * <ul>
+ * <li><code>OS_</code> OS path constant. These paths are different depending on the platform.</li>
+ * <li><code>FN_</code> File name constant.</li>
+ * <li><code>FD_</code> Folder name constant.</li>
+ * </ul>
+ *
+ */
+public final class SdkConstants {
+
+ /** Name of the framework library, i.e. "android.jar" */
+ public static final String FN_FRAMEWORK_LIBRARY = "android.jar";
+ /** Name of the layout attributes, i.e. "attrs.xml" */
+ public static final String FN_ATTRS_XML = "attrs.xml";
+ /** Name of the layout attributes, i.e. "attrs_manifest.xml" */
+ public static final String FN_ATTRS_MANIFEST_XML = "attrs_manifest.xml";
+ /** framework aidl import file */
+ public static final String FN_FRAMEWORK_AIDL = "framework.aidl";
+ /** layoutlib.jar file */
+ public static final String FN_LAYOUTLIB_JAR = "layoutlib.jar";
+ /** widget list file */
+ public static final String FN_WIDGETS = "widgets.txt";
+ /** Intent activity actions list file */
+ public static final String FN_INTENT_ACTIONS_ACTIVITY = "activity_actions.txt";
+ /** Intent broadcast actions list file */
+ public static final String FN_INTENT_ACTIONS_BROADCAST = "broadcast_actions.txt";
+ /** Intent service actions list file */
+ public static final String FN_INTENT_ACTIONS_SERVICE = "service_actions.txt";
+ /** Intent category list file */
+ public static final String FN_INTENT_CATEGORIES = "categories.txt";
+
+ /** platform build property file */
+ public final static String FN_BUILD_PROP = "build.prop";
+ /** plugin properties file */
+ public final static String FN_PLUGIN_PROP = "plugin.prop";
+ /** add-on manifest file */
+ public final static String FN_MANIFEST_INI = "manifest.ini";
+ /** hardware properties definition file */
+ public final static String FN_HARDWARE_INI = "hardware-properties.ini";
+
+ /** Skin layout file */
+ public final static String FN_SKIN_LAYOUT = "layout";//$NON-NLS-1$
+
+ /* Folder Names for the Android SDK */
+
+ /** Name of the SDK platforms folder. */
+ public final static String FD_PLATFORMS = "platforms";
+ /** Name of the SDK addons folder. */
+ public final static String FD_ADDONS = "add-ons";
+ /** Name of the SDK tools folder. */
+ public final static String FD_TOOLS = "tools";
+ /** Name of the SDK tools/lib folder. */
+ public final static String FD_LIB = "lib";
+ /** Name of the SDK docs folder. */
+ public final static String FD_DOCS = "docs";
+ /** Name of the SDK images folder. */
+ public final static String FD_IMAGES = "images";
+ /** Name of the SDK skins folder. */
+ public final static String FD_SKINS = "skins";
+ /** Name of the SDK samples folder. */
+ public final static String FD_SAMPLES = "samples";
+ /** Name of the SDK templates folder, i.e. "templates" */
+ public final static String FD_TEMPLATES = "templates";
+ /** Name of the SDK data folder, i.e. "data" */
+ public final static String FD_DATA = "data";
+ /** Name of the SDK resources folder, i.e. "res" */
+ public final static String FD_RES = "res";
+ /** Name of the SDK font folder, i.e. "fonts" */
+ public final static String FD_FONTS = "fonts";
+ /** Default values resource folder name, i.e. "values" */
+ public final static String FD_VALUES = "values";
+ /** Name of the android sources directory */
+ public static final String FD_ANDROID_SOURCES = "sources";
+ /** Name of the addon libs folder. */
+ public final static String FD_ADDON_LIBS = "libs";
+
+ /* Folder path relative to the SDK root */
+ /** Path of the documentation directory relative to the sdk folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_SDK_DOCS_FOLDER = FD_DOCS + File.separator;
+
+ /** Path of the tools directory relative to the sdk folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_SDK_TOOLS_FOLDER = FD_TOOLS + File.separator;
+
+ /** Path of the lib directory relative to the sdk folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_SDK_TOOLS_LIB_FOLDER =
+ OS_SDK_TOOLS_FOLDER + FD_LIB + File.separator;
+
+ /* Folder paths relative to a platform or add-on folder */
+
+ /** Path of the images directory relative to a platform or addon folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_IMAGES_FOLDER = FD_IMAGES + File.separator;
+
+ /** Path of the skin directory relative to a platform or addon folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_SKINS_FOLDER = FD_SKINS + File.separator;
+
+ /* Folder paths relative to a Platform folder */
+
+ /** Path of the data directory relative to a platform folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_PLATFORM_DATA_FOLDER = FD_DATA + File.separator;
+
+ /** Path of the samples directory relative to a platform folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_PLATFORM_SAMPLES_FOLDER = FD_SAMPLES + File.separator;
+
+ /** Path of the resources directory relative to a platform folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_PLATFORM_RESOURCES_FOLDER =
+ OS_PLATFORM_DATA_FOLDER + FD_RES + File.separator;
+
+ /** Path of the fonts directory relative to a platform folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_PLATFORM_FONTS_FOLDER =
+ OS_PLATFORM_DATA_FOLDER + FD_FONTS + File.separator;
+
+ /** Path of the android source directory relative to a platform folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_PLATFORM_SOURCES_FOLDER = FD_ANDROID_SOURCES + File.separator;
+
+ /** Path of the android templates directory relative to a platform folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_PLATFORM_TEMPLATES_FOLDER = FD_TEMPLATES + File.separator;
+
+ /** Path of the attrs.xml file relative to a platform folder. */
+ public final static String OS_PLATFORM_ATTRS_XML =
+ OS_PLATFORM_RESOURCES_FOLDER + FD_VALUES + File.separator + FN_ATTRS_XML;
+
+ /** Path of the attrs_manifest.xml file relative to a platform folder. */
+ public final static String OS_PLATFORM_ATTRS_MANIFEST_XML =
+ OS_PLATFORM_RESOURCES_FOLDER + FD_VALUES + File.separator + FN_ATTRS_MANIFEST_XML;
+
+ /** Path of the layoutlib.jar file relative to a platform folder. */
+ public final static String OS_PLATFORM_LAYOUTLIB_JAR =
+ OS_PLATFORM_DATA_FOLDER + FN_LAYOUTLIB_JAR;
+
+ /* Folder paths relative to a addon folder */
+
+ /** Path of the images directory relative to a folder folder.
+ * This is an OS path, ending with a separator. */
+ public final static String OS_ADDON_LIBS_FOLDER = FD_ADDON_LIBS + File.separator;
+
+
+ /* Skin default */
+ public final static String SKIN_DEFAULT = "default";
+
+}
diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java
new file mode 100644
index 0000000..67b8499
--- /dev/null
+++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java
@@ -0,0 +1,420 @@
+/*
+ * 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.sdklib;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * The SDK manager parses the SDK folder and gives access to the content.
+ * @see PlatformTarget
+ * @see AddOnTarget
+ */
+public final class SdkManager {
+
+ private final static String PROP_VERSION_SDK = "ro.build.version.sdk";
+ private final static String PROP_VERSION_RELEASE = "ro.build.version.release";
+
+ private final static String ADDON_NAME = "name";
+ private final static String ADDON_VENDOR = "vendor";
+ private final static String ADDON_API = "api";
+ private final static String ADDON_DESCRIPTION = "description";
+ private final static String ADDON_LIBRARIES = "libraries";
+
+ private final static Pattern PATTERN_PROP = Pattern.compile(
+ "^([a-zA-Z0-9._-]+)\\s*=\\s*(.*)\\s*$");
+
+ /** the location of the SDK */
+ private final String mSdkLocation;
+ private IAndroidTarget[] mTargets;
+
+ /**
+ * Creates an {@link SdkManager} for a given sdk location.
+ * @param sdkLocation the location of the SDK.
+ * @param log the ISdkLog object receiving warning/error from the parsing.
+ * @return the created {@link SdkManager} or null if the location is not valid.
+ */
+ public static SdkManager createManager(String sdkLocation, ISdkLog log) {
+ try {
+ SdkManager manager = new SdkManager(sdkLocation);
+ ArrayList<IAndroidTarget> list = new ArrayList<IAndroidTarget>();
+ manager.loadPlatforms(list, log);
+ manager.loadAddOns(list, log);
+
+ // sort the targets/add-ons
+ Collections.sort(list);
+
+ manager.setTargets(list.toArray(new IAndroidTarget[list.size()]));
+
+ return manager;
+ } catch (IllegalArgumentException e) {
+ if (log != null) {
+ log.error(e.getMessage());
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the location of the SDK.
+ */
+ public String getLocation() {
+ return mSdkLocation;
+ }
+
+ /**
+ * Returns the targets that are available in the SDK.
+ */
+ public IAndroidTarget[] getTargets() {
+ return mTargets;
+ }
+
+ /**
+ * Returns a target from a hash that was generated by {@link IAndroidTarget#hashString()}.
+ * @param hash the hash
+ */
+ public IAndroidTarget getTargetFromHashString(String hash) {
+ if (hash != null) {
+ for (IAndroidTarget target : mTargets) {
+ if (hash.equals(target.hashString())) {
+ return target;
+ }
+ }
+ }
+
+ return null;
+ }
+
+
+ private SdkManager(String sdkLocation) {
+ mSdkLocation = sdkLocation;
+ }
+
+ private void setTargets(IAndroidTarget[] targets) {
+ mTargets = targets;
+ }
+
+ /**
+ * Loads the Platforms from the SDK.
+ * @param list the list to fill with the platforms.
+ * @param log the ISdkLog object receiving warning/error from the parsing.
+ */
+ private void loadPlatforms(ArrayList<IAndroidTarget> list, ISdkLog log) {
+ File platformFolder = new File(mSdkLocation, SdkConstants.FD_PLATFORMS);
+ if (platformFolder.isDirectory()) {
+ File[] platforms = platformFolder.listFiles();
+
+ for (File platform : platforms) {
+ if (platform.isDirectory()) {
+ PlatformTarget target = loadPlatform(platform, log);
+ if (target != null) {
+ list.add(target);
+ }
+ } else if (log != null) {
+ log.warning("Ignoring platform '%1$s', not a folder.", platform.getName());
+ }
+ }
+
+ return;
+ }
+
+ String message = null;
+ if (platformFolder.exists() == false) {
+ message = "%s is missing.";
+ } else {
+ message = "%s is not a folder.";
+ }
+
+ throw new IllegalArgumentException(String.format(message,
+ platformFolder.getAbsolutePath()));
+ }
+
+ /**
+ * Loads a specific Platform at a given location.
+ * @param platform the location of the platform.
+ * @param log the ISdkLog object receiving warning/error from the parsing.
+ */
+ private PlatformTarget loadPlatform(File platform, ISdkLog log) {
+ File buildProp = new File(platform, SdkConstants.FN_BUILD_PROP);
+
+ if (buildProp.isFile()) {
+ Map<String, String> map = parsePropertyFile(buildProp, log);
+
+ if (map != null) {
+ // look for some specific values in the map.
+ try {
+ String apiNumber = map.get(PROP_VERSION_SDK);
+ String apiName = map.get(PROP_VERSION_RELEASE);
+ if (apiNumber != null && apiName != null) {
+ // create the target.
+ PlatformTarget target = new PlatformTarget(
+ platform.getAbsolutePath(),
+ map,
+ Integer.parseInt(apiNumber),
+ apiName);
+
+ // need to parse the skins.
+ String[] skins = parseSkinFolder(target.getPath(IAndroidTarget.SKINS));
+ target.setSkins(skins);
+
+ return target;
+ }
+ } catch (NumberFormatException e) {
+ // looks like apiNumber does not parse to a number.
+ // Ignore this platform.
+ if (log != null) {
+ log.error("Ignoring platform '%1$s': %2$s is not a valid number in %3$s.",
+ platform.getName(), PROP_VERSION_SDK, SdkConstants.FN_BUILD_PROP);
+ }
+ }
+ }
+ } else if (log != null) {
+ log.error("Ignoring platform '%1$s': %2$s is missing.", platform.getName(),
+ SdkConstants.FN_BUILD_PROP);
+ }
+
+ return null;
+ }
+
+ /**
+ * Loads the Add-on from the SDK.
+ * @param list the list to fill with the add-ons.
+ * @param log the ISdkLog object receiving warning/error from the parsing.
+ */
+ private void loadAddOns(ArrayList<IAndroidTarget> list, ISdkLog log) {
+ File addonFolder = new File(mSdkLocation, SdkConstants.FD_ADDONS);
+ if (addonFolder.isDirectory()) {
+ File[] addons = addonFolder.listFiles();
+
+ for (File addon : addons) {
+ if (addon.isDirectory()) {
+ AddOnTarget target = loadAddon(addon, list, log);
+ if (target != null) {
+ list.add(target);
+ }
+ } else if (log != null) {
+ log.warning("Ignoring add-on '%1$s', not a folder.", addon.getName());
+ }
+ }
+
+ return;
+ }
+
+ String message = null;
+ if (addonFolder.exists() == false) {
+ message = "%s is missing.";
+ } else {
+ message = "%s is not a folder.";
+ }
+
+ throw new IllegalArgumentException(String.format(message,
+ addonFolder.getAbsolutePath()));
+ }
+
+ /**
+ * Loads a specific Add-on at a given location.
+ * @param addon the location of the addon.
+ * @param list
+ * @param log
+ */
+ private AddOnTarget loadAddon(File addon, ArrayList<IAndroidTarget> list, ISdkLog log) {
+ File addOnManifest = new File(addon, SdkConstants.FN_MANIFEST_INI);
+
+ if (addOnManifest.isFile()) {
+ Map<String, String> map = parsePropertyFile(addOnManifest, log);
+
+ if (map != null) {
+ // look for some specific values in the map.
+ // we require name, vendor, and api
+ String name = map.get(ADDON_NAME);
+ if (name == null) {
+ displayAddonManifestError(log, addon.getName(), ADDON_NAME);
+ return null;
+ }
+
+ String vendor = map.get(ADDON_VENDOR);
+ if (vendor == null) {
+ displayAddonManifestError(log, addon.getName(), ADDON_VENDOR);
+ return null;
+ }
+
+ String api = map.get(ADDON_API);
+ PlatformTarget baseTarget = null;
+ if (api == null) {
+ displayAddonManifestError(log, addon.getName(), ADDON_API);
+ return null;
+ } else {
+ try {
+ int apiValue = Integer.parseInt(api);
+ for (IAndroidTarget target : list) {
+ if (target.isPlatform() &&
+ target.getApiVersionNumber() == apiValue) {
+ baseTarget = (PlatformTarget)target;
+ break;
+ }
+ }
+
+ if (baseTarget == null) {
+ if (log != null) {
+ log.error(
+ "Ignoring add-on '%1$s': Unable to find base platform with API level %2$d",
+ addon.getName(), apiValue);
+ }
+
+ return null;
+ }
+ } catch (NumberFormatException e) {
+ // looks like apiNumber does not parse to a number.
+ // Ignore this add-on.
+ if (log != null) {
+ log.error(
+ "Ignoring add-on '%1$s': %2$s is not a valid number in %3$s.",
+ addon.getName(), ADDON_API, SdkConstants.FN_BUILD_PROP);
+ }
+ return null;
+ }
+ }
+
+ // get the optional description
+ String description = map.get(ADDON_DESCRIPTION);
+
+ // get the optional libraries
+ String librariesValue = map.get(ADDON_LIBRARIES);
+
+ // split in the string into the values we care about
+ String[] libraries = librariesValue.split(";");
+ Map<String, String> libMap = null;
+ if (libraries.length > 0) {
+ libMap = new HashMap<String, String>();
+ for (String lib : libraries) {
+ String[] values = lib.split(":");
+ if (values.length == 2) {
+ libMap.put(values[0], values[1]);
+ } else {
+ // TODO: log error
+ }
+ }
+ }
+
+ AddOnTarget target = new AddOnTarget(addon.getAbsolutePath(), name, vendor,
+ description, libMap, baseTarget);
+
+ // need to parse the skins.
+ String[] skins = parseSkinFolder(target.getPath(IAndroidTarget.SKINS));
+ target.setSkins(skins);
+
+ return target;
+ }
+ } else if (log != null) {
+ log.error("Ignoring add-on '%1$s': %2$s is missing.", addon.getName(),
+ SdkConstants.FN_MANIFEST_INI);
+ }
+
+ return null;
+ }
+
+ private void displayAddonManifestError(ISdkLog log, String addonName, String valueName) {
+ if (log != null) {
+ log.error("Ignoring add-on '%1$s': '%2$s' is missing from %3$s.",
+ addonName, valueName, SdkConstants.FN_MANIFEST_INI);
+ }
+ }
+
+ /**
+ * Parses a property file and returns
+ * @param buildProp the property file to parse
+ * @param log the ISdkLog object receiving warning/error from the parsing.
+ * @return the map of (key,value) pairs, or null if the parsing failed.
+ */
+ public static Map<String, String> parsePropertyFile(File buildProp, ISdkLog log) {
+ try {
+ FileInputStream fis = new FileInputStream(buildProp);
+ BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
+
+ String line = null;
+ Map<String, String> map = new HashMap<String, String>();
+ while ((line = reader.readLine()) != null) {
+ if (line.length() > 0 && line.charAt(0) != '#') {
+
+ Matcher m = PATTERN_PROP.matcher(line);
+ if (m.matches()) {
+ map.put(m.group(1), m.group(2));
+ } else {
+ log.warning("Error parsing '%1$s': \"%2$s\" is not a valid syntax",
+ buildProp.getAbsolutePath(), line);
+ return null;
+ }
+ }
+ }
+
+ return map;
+ } catch (FileNotFoundException e) {
+ // this should not happen since we usually test the file existence before
+ // calling the method.
+ // Return null below.
+ } catch (IOException e) {
+ if (log != null) {
+ log.warning("Error parsing '%1$s': %2$s.", buildProp.getAbsolutePath(),
+ e.getMessage());
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Parses the skin folder and builds the skin list.
+ * @param osPath The path of the skin root folder.
+ */
+ private String[] parseSkinFolder(String osPath) {
+ File skinRootFolder = new File(osPath);
+
+ if (skinRootFolder.isDirectory()) {
+ ArrayList<String> skinList = new ArrayList<String>();
+
+ File[] files = skinRootFolder.listFiles();
+
+ for (File skinFolder : files) {
+ if (skinFolder.isDirectory()) {
+ // check for layout file
+ File layout = new File(skinFolder, SdkConstants.FN_SKIN_LAYOUT);
+
+ if (layout.isFile()) {
+ // for now we don't parse the content of the layout and
+ // simply add the directory to the list.
+ skinList.add(skinFolder.getName());
+ }
+ }
+ }
+
+ return skinList.toArray(new String[skinList.size()]);
+ }
+
+ return new String[0];
+ }
+}
diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/project/ProjectProperties.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/project/ProjectProperties.java
new file mode 100644
index 0000000..c0c1fe3
--- /dev/null
+++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/project/ProjectProperties.java
@@ -0,0 +1,136 @@
+/*
+ * 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.sdklib.project;
+
+import com.android.sdklib.SdkManager;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * Class to load and save project properties for both ADT and Ant-based build.
+ *
+ */
+public final class ProjectProperties {
+ /** The property name for the project target */
+ public final static String PROPERTY_TARGET = "target";
+ public final static String PROPERTY_SDK = "sdk-folder";
+
+ private final static String PROPERTIES_FILE = "default.properties";
+
+ private final static String PROP_HEADER =
+ "# This file is automatically generated by Android Tools.\n" +
+ "# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n" +
+ "# For customized properties when using Ant, set new values\n" +
+ "# in a \"build.properties\" file.\n\n";
+
+ private final static Map<String, String> COMMENT_MAP = new HashMap<String, String>();
+ static {
+ COMMENT_MAP.put(PROPERTY_TARGET, "# Project target.\n");
+ COMMENT_MAP.put(PROPERTY_SDK, "# location of the SDK. Only used by Ant.\n");
+ }
+
+ private final String mProjectFolderOsPath;
+ private final Map<String, String> mProperties;
+
+ /**
+ * Loads a project properties file and return a {@link ProjectProperties} object
+ * containing the properties
+ * @param projectFolderOsPath the project folder.
+ */
+ public static ProjectProperties load(String projectFolderOsPath) {
+ File projectFolder = new File(projectFolderOsPath);
+ if (projectFolder.isDirectory()) {
+ File defaultFile = new File(projectFolder, PROPERTIES_FILE);
+ if (defaultFile.isFile()) {
+ Map<String, String> map = SdkManager.parsePropertyFile(defaultFile, null /* log */);
+ if (map != null) {
+ return new ProjectProperties(projectFolderOsPath, map);
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Creates a new project properties file, with no properties.
+ * <p/>The file is not created until {@link #save()} is called.
+ * @param projectFolderOsPath the project folder.
+ */
+ public static ProjectProperties create(String projectFolderOsPath) {
+ // create and return a ProjectProperties with an empty map.
+ return new ProjectProperties(projectFolderOsPath, new HashMap<String, String>());
+ }
+
+ /**
+ * Sets a new properties. If a property with the same name already exists, it is replaced.
+ * @param name the name of the property.
+ * @param value the value of the property.
+ */
+ public void setProperty(String name, String value) {
+ mProperties.put(name, value);
+ }
+
+ /**
+ * Returns the value of a property.
+ * @param name the name of the property.
+ * @return the property value or null if the property is not set.
+ */
+ public String getProperty(String name) {
+ return mProperties.get(name);
+ }
+
+ /**
+ * Saves the property file.
+ * @throws IOException
+ */
+ public void save() throws IOException {
+ File toSave = new File(mProjectFolderOsPath, PROPERTIES_FILE);
+
+ FileWriter writer = new FileWriter(toSave);
+
+ // write the header
+ writer.write(PROP_HEADER);
+
+ // write the properties.
+ for (Entry<String, String> entry : mProperties.entrySet()) {
+ String comment = COMMENT_MAP.get(entry.getKey());
+ if (comment != null) {
+ writer.write(comment);
+ }
+ writer.write(String.format("%s=%s\n", entry.getKey(), entry.getValue()));
+ }
+
+ // close the file to flush
+ writer.close();
+ }
+
+ /**
+ * Private constructor.
+ * Use {@link #load(String)} or {@link #create(String)} to instantiate.
+ * @param projectFolderOsPath
+ * @param map
+ */
+ private ProjectProperties(String projectFolderOsPath, Map<String, String> map) {
+ mProjectFolderOsPath = projectFolderOsPath;
+ mProperties = map;
+ }
+}
diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/vm/HardwareProperties.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/vm/HardwareProperties.java
new file mode 100644
index 0000000..cb2c8c2
--- /dev/null
+++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/vm/HardwareProperties.java
@@ -0,0 +1,159 @@
+/*
+ * 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.sdklib.vm;
+
+import com.android.sdklib.ISdkLog;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class HardwareProperties {
+ private final static Pattern PATTERN_PROP = Pattern.compile(
+ "^([a-zA-Z0-9._-]+)\\s*=\\s*(.*)\\s*$");
+
+ private final static String HW_PROP_NAME = "name";
+ private final static String HW_PROP_TYPE = "type";
+ private final static String HW_PROP_DEFAULT = "default";
+ private final static String HW_PROP_ABSTRACT = "abstract";
+ private final static String HW_PROP_DESC = "description";
+
+ public enum ValueType {
+ INTEGER("integer"),
+ BOOLEAN("boolean"),
+ DISKSIZE("diskSize");
+
+ private String mValue;
+
+ ValueType(String value) {
+ mValue = value;
+ }
+
+ public static ValueType getEnum(String value) {
+ for (ValueType type : values()) {
+ if (type.mValue.equals(value)) {
+ return type;
+ }
+ }
+
+ return null;
+ }
+ }
+
+ public static final class HardwareProperty {
+ private String mName;
+ private ValueType mType;
+ /** the string representation of the default value. can be null. */
+ private String mDefault;
+ private String mAbstract;
+ private String mDescription;
+
+ public String getName() {
+ return mName;
+ }
+
+ public ValueType getType() {
+ return mType;
+ }
+
+ public String getDefault() {
+ return mDefault;
+ }
+
+ public String getAbstract() {
+ return mAbstract;
+ }
+
+ public String getDescription() {
+ return mDescription;
+ }
+ }
+
+ /**
+ * Parses the harware definition file.
+ * @param buildProp the property file to parse
+ * @param log the ISdkLog object receiving warning/error from the parsing.
+ * @return the map of (key,value) pairs, or null if the parsing failed.
+ */
+ public static List<HardwareProperty> parseHardwareDefinitions(File file, ISdkLog log) {
+ try {
+ FileInputStream fis = new FileInputStream(file);
+ BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
+
+ List<HardwareProperty> map = new ArrayList<HardwareProperty>();
+
+ String line = null;
+ HardwareProperty prop = null;
+ while ((line = reader.readLine()) != null) {
+ if (line.length() > 0 && line.charAt(0) != '#') {
+ Matcher m = PATTERN_PROP.matcher(line);
+ if (m.matches()) {
+ String valueName = m.group(1);
+ String value = m.group(2);
+
+ if (HW_PROP_NAME.equals(valueName)) {
+ prop = new HardwareProperty();
+ prop.mName = value;
+ map.add(prop);
+ }
+
+ if (prop == null) {
+ log.warning("Error parsing '%1$s': missing '%2$s'",
+ file.getAbsolutePath(), HW_PROP_NAME);
+ return null;
+ }
+
+ if (HW_PROP_TYPE.equals(valueName)) {
+ prop.mType = ValueType.getEnum(value);
+ } else if (HW_PROP_DEFAULT.equals(valueName)) {
+ prop.mDefault = value;
+ } else if (HW_PROP_ABSTRACT.equals(valueName)) {
+ prop.mAbstract = value;
+ } else if (HW_PROP_DESC.equals(valueName)) {
+ prop.mDescription = value;
+ }
+ } else {
+ log.warning("Error parsing '%1$s': \"%2$s\" is not a valid syntax",
+ file.getAbsolutePath(), line);
+ return null;
+ }
+ }
+ }
+
+ return map;
+ } catch (FileNotFoundException e) {
+ // this should not happen since we usually test the file existence before
+ // calling the method.
+ // Return null below.
+ } catch (IOException e) {
+ if (log != null) {
+ log.warning("Error parsing '%1$s': %2$s.", file.getAbsolutePath(),
+ e.getMessage());
+ }
+ }
+
+ return null;
+ }
+
+}
diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/vm/VmManager.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/vm/VmManager.java
new file mode 100644
index 0000000..a9f1b17
--- /dev/null
+++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/vm/VmManager.java
@@ -0,0 +1,258 @@
+/*
+ * 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.sdklib.vm;
+
+import com.android.prefs.AndroidLocation;
+import com.android.prefs.AndroidLocation.AndroidLocationException;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.ISdkLog;
+import com.android.sdklib.SdkConstants;
+import com.android.sdklib.SdkManager;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Virtual Machine manager to access the list of VMs or create new ones.
+ */
+public final class VmManager {
+
+ private final static String VM_INFO_PATH = "path";
+ private final static String VM_INFO_TARGET = "target";
+
+ private final static String IMAGE_USERDATA = "userdata.img";
+ private final static String CONFIG_INI = "config.ini";
+
+ private final static Pattern INI_NAME_PATTERN = Pattern.compile("(.+)\\.ini$",
+ Pattern.CASE_INSENSITIVE);
+
+ public static final class VmInfo {
+ String name;
+ String path;
+ IAndroidTarget target;
+
+ public String getName() {
+ return name;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public IAndroidTarget getTarget() {
+ return target;
+ }
+ }
+
+ private final ArrayList<VmInfo> mVmList = new ArrayList<VmInfo>();
+ private ISdkLog mSdkLog;
+
+ public VmManager(SdkManager sdk, ISdkLog sdkLog) throws AndroidLocationException {
+ mSdkLog = sdkLog;
+ buildVmList(sdk);
+ }
+
+ public VmInfo[] getVms() {
+ return mVmList.toArray(new VmInfo[mVmList.size()]);
+ }
+
+ /**
+ * Creates a new VM.
+ * @param parentFolder the folder to contain the VM. A new folder will be created in this
+ * folder with the name of the VM
+ * @param name the name of the VM
+ * @param target the target of the VM
+ * @param skinName the name of the skin. Can be null.
+ * @param sdcardPath the path to the sdCard. Can be null.
+ * @param sdcardSize the size of a local sdcard to create. Can be 0 for no local sdcard.
+ * @param hardwareConfig the hardware setup for the VM
+ */
+ public static void createVm(String parentFolder, String name, IAndroidTarget target,
+ String skinName, String sdcardPath, int sdcardSize, Map<String,String> hardwareConfig,
+ ISdkLog log) {
+
+ // now write the ini file in the vmRoot folder.
+ // get the Android prefs location.
+ try {
+ File rootDirectory = new File(parentFolder);
+ if (rootDirectory.isDirectory() == false) {
+ if (log != null) {
+ log.error("%s does not exists.", parentFolder);
+ }
+ return;
+ }
+
+ File vmFolder = new File(parentFolder, name + ".avm");
+ if (vmFolder.exists()) {
+ if (log != null) {
+ log.error("%s already exists.", vmFolder.getAbsolutePath());
+ }
+ return;
+ }
+
+ // create the vm folder.
+ vmFolder.mkdir();
+
+ HashMap<String, String> values = new HashMap<String, String>();
+
+ // prepare the ini file.
+ String vmRoot = AndroidLocation.getFolder() + AndroidLocation.FOLDER_VMS;
+ File iniFile = new File(vmRoot, name + ".ini");
+ values.put(VM_INFO_PATH, vmFolder.getAbsolutePath());
+ values.put(VM_INFO_TARGET, target.hashString());
+ createConfigIni(iniFile, values);
+
+ // writes the userdata.img in it.
+ String imagePath = target.getPath(IAndroidTarget.IMAGES);
+ File userdataSrc = new File(imagePath, IMAGE_USERDATA);
+ FileInputStream fis = new FileInputStream(userdataSrc);
+
+ File userdataDest = new File(vmFolder, IMAGE_USERDATA);
+ FileOutputStream fos = new FileOutputStream(userdataDest);
+
+ byte[] buffer = new byte[4096];
+ int count;
+ while ((count = fis.read(buffer)) != -1) {
+ fos.write(buffer, 0, count);
+ }
+
+ fos.close();
+ fis.close();
+
+ // Config file
+ values.clear();
+ if (skinName != null) {
+ values.put("skin", skinName);
+ } else {
+ values.put("skin", SdkConstants.SKIN_DEFAULT);
+ }
+
+ if (sdcardPath != null) {
+ values.put("sdcard", sdcardPath);
+ } else if (sdcardSize != 0) {
+ // TODO: create sdcard image.
+ }
+
+ if (hardwareConfig != null) {
+ values.putAll(hardwareConfig);
+ }
+
+ File configIniFile = new File(vmFolder, CONFIG_INI);
+ createConfigIni(configIniFile, values);
+
+ if (target.isPlatform()) {
+ System.out.println(String.format(
+ "Created VM '%s' based on %s", name, target.getName()));
+ } else {
+ System.out.println(String.format(
+ "Created VM '%s' based on %s (%s)", name, target.getName(),
+ target.getVendor()));
+ }
+ } catch (AndroidLocationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ private void buildVmList(SdkManager sdk) throws AndroidLocationException {
+ // get the Android prefs location.
+ String vmRoot = AndroidLocation.getFolder() + AndroidLocation.FOLDER_VMS;
+
+ // ensure folder validity.
+ File folder = new File(vmRoot);
+ if (folder.isFile()) {
+ throw new AndroidLocationException(String.format("%s is not a valid folder.", vmRoot));
+ } else if (folder.exists() == false) {
+ // folder is not there, we create it and return
+ folder.mkdirs();
+ return;
+ }
+
+ File[] vms = folder.listFiles(new FilenameFilter() {
+ public boolean accept(File parent, String name) {
+ if (INI_NAME_PATTERN.matcher(name).matches()) {
+ // check it's a file and not a folder
+ return new File(parent, name).isFile();
+ }
+
+ return false;
+ }
+ });
+
+ for (File vm : vms) {
+ VmInfo info = parseVmInfo(vm, sdk);
+ if (info != null) {
+ mVmList.add(info);
+ }
+ }
+ }
+
+ private VmInfo parseVmInfo(File path, SdkManager sdk) {
+ Map<String, String> map = SdkManager.parsePropertyFile(path, mSdkLog);
+
+ String vmPath = map.get(VM_INFO_PATH);
+ if (vmPath == null) {
+ return null;
+ }
+
+ String targetHash = map.get(VM_INFO_TARGET);
+ if (targetHash == null) {
+ return null;
+ }
+
+ IAndroidTarget target = sdk.getTargetFromHashString(targetHash);
+ if (target == null) {
+ return null;
+ }
+
+ VmInfo info = new VmInfo();
+ Matcher matcher = INI_NAME_PATTERN.matcher(path.getName());
+ if (matcher.matches()) {
+ info.name = matcher.group(1);
+ } else {
+ info.name = path.getName(); // really this should not happen.
+ }
+ info.path = vmPath;
+ info.target = target;
+
+ return info;
+ }
+
+ private static void createConfigIni(File iniFile, Map<String, String> values)
+ throws IOException {
+ FileWriter writer = new FileWriter(iniFile);
+
+ for (Entry<String, String> entry : values.entrySet()) {
+ writer.write(String.format("%s=%s\n", entry.getKey(), entry.getValue()));
+ }
+ writer.close();
+
+ }
+}
diff --git a/tools/sdkmanager/libs/sdkuilib/Android.mk b/tools/sdkmanager/libs/sdkuilib/Android.mk
new file mode 100644
index 0000000..8e0bc23
--- /dev/null
+++ b/tools/sdkmanager/libs/sdkuilib/Android.mk
@@ -0,0 +1,4 @@
+# Copyright 2008 The Android Open Source Project
+#
+SDKUILIB_LOCAL_DIR := $(call my-dir)
+include $(SDKUILIB_LOCAL_DIR)/src/Android.mk
diff --git a/tools/sdkmanager/libs/sdkuilib/README b/tools/sdkmanager/libs/sdkuilib/README
new file mode 100644
index 0000000..d66b84a
--- /dev/null
+++ b/tools/sdkmanager/libs/sdkuilib/README
@@ -0,0 +1,11 @@
+Using the Eclipse projects for ddmuilib.
+
+ddmuilib requires SWT to compile.
+
+SWT is available in the depot under prebuild/<platform>/swt
+
+Because the build path cannot contain relative path that are not inside the project directory,
+the .classpath file references a user library called ANDROID_SWT.
+
+In order to compile the project, make a user library called ANDROID_SWT containing the jar
+available at prebuild/<platform>/swt.
\ No newline at end of file
diff --git a/tools/sdkmanager/libs/sdkuilib/src/Android.mk b/tools/sdkmanager/libs/sdkuilib/src/Android.mk
new file mode 100644
index 0000000..2d3c774
--- /dev/null
+++ b/tools/sdkmanager/libs/sdkuilib/src/Android.mk
@@ -0,0 +1,21 @@
+# Copyright 2008 The Android Open Source Project
+#
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+# no resources yet.
+# LOCAL_JAVA_RESOURCE_DIRS := resources
+
+LOCAL_JAVA_LIBRARIES := \
+ sdklib \
+ swt \
+ org.eclipse.jface_3.2.0.I20060605-1400 \
+ org.eclipse.equinox.common_3.2.0.v20060603 \
+ org.eclipse.core.commands_3.2.0.I20060605-1400
+
+LOCAL_MODULE := sdkuilib
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/SdkTargetSelector.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/SdkTargetSelector.java
new file mode 100644
index 0000000..ddc492e
--- /dev/null
+++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/SdkTargetSelector.java
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.sdkuilib;
+
+import com.android.sdklib.IAndroidTarget;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+
+import java.util.ArrayList;
+
+
+/**
+ * The SDK target selector is a table that is added to the given parent composite.
+ */
+public class SdkTargetSelector {
+
+ private final IAndroidTarget[] mTargets;
+ private final boolean mAllowMultipleSelection;
+ private SelectionListener mSelectionListener;
+ private Table mTable;
+ private Label mDescription;
+
+ public SdkTargetSelector(Composite parent, IAndroidTarget[] targets,
+ boolean allowMultipleSelection) {
+ mTargets = targets;
+
+ // Layout has 1 column
+ Composite group = new Composite(parent, SWT.NONE);
+ group.setLayout(new GridLayout());
+ group.setLayoutData(new GridData(GridData.FILL_BOTH));
+ group.setFont(parent.getFont());
+
+ mAllowMultipleSelection = allowMultipleSelection;
+ mTable = new Table(group, SWT.CHECK | SWT.FULL_SELECTION | SWT.SINGLE | SWT.BORDER);
+ mTable.setHeaderVisible(true);
+ mTable.setLinesVisible(false);
+
+ GridData data = new GridData();
+ data.grabExcessVerticalSpace = true;
+ data.grabExcessHorizontalSpace = true;
+ data.horizontalAlignment = GridData.FILL;
+ data.verticalAlignment = GridData.FILL;
+ mTable.setLayoutData(data);
+
+ mDescription = new Label(group, SWT.WRAP);
+ mDescription.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ // create the table columns
+ final TableColumn column0 = new TableColumn(mTable, SWT.NONE);
+ column0.setText("SDK Target");
+ final TableColumn column1 = new TableColumn(mTable, SWT.NONE);
+ column1.setText("Vendor");
+ final TableColumn column2 = new TableColumn(mTable, SWT.NONE);
+ column2.setText("API Level");
+
+ adjustColumnsWidth(mTable, column0, column1, column2);
+ setupSelectionListener(mTable);
+ fillTable(mTable);
+ setupTooltip(mTable);
+ }
+
+ /**
+ * Sets a selection listener. Set it to null to remove it.
+ * The listener will be called <em>after</em> this table processed its selection
+ * events so that the caller can see the updated state.
+ * <p/>
+ * The event's item contains a {@link TableItem}.
+ * The {@link TableItem#getData()} contains an {@link IAndroidTarget}.
+ * <p/>
+ * It is recommended that the caller uses the {@link #getFirstSelected()} and
+ * {@link #getAllSelected()} methods instead.
+ *
+ * @param selectionListener The new listener or null to remove it.
+ */
+ public void setSelectionListener(SelectionListener selectionListener) {
+ mSelectionListener = selectionListener;
+ }
+
+ /**
+ * Sets the current target selection.
+ * @param target the target to be selection
+ * @return true if the target could be selected, false otherwise.
+ */
+ public boolean setSelection(IAndroidTarget target) {
+ boolean found = false;
+ for (TableItem i : mTable.getItems()) {
+ if ((IAndroidTarget) i.getData() == target) {
+ found = true;
+ i.setChecked(true);
+ } else {
+ i.setChecked(false);
+ }
+ }
+
+ return found;
+ }
+
+ /**
+ * Returns all selected items.
+ * This is useful when the table is in multiple-selection mode.
+ *
+ * @see #getFirstSelected()
+ * @return An array of selected items. The list can be empty but not null.
+ */
+ public IAndroidTarget[] getAllSelected() {
+ ArrayList<IAndroidTarget> list = new ArrayList<IAndroidTarget>();
+ for (TableItem i : mTable.getItems()) {
+ if (i.getChecked()) {
+ list.add((IAndroidTarget) i.getData());
+ }
+ }
+ return list.toArray(new IAndroidTarget[list.size()]);
+ }
+
+ /**
+ * Returns the first selected item.
+ * This is useful when the table is in single-selection mode.
+ *
+ * @see #getAllSelected()
+ * @return The first selected item or null.
+ */
+ public IAndroidTarget getFirstSelected() {
+ for (TableItem i : mTable.getItems()) {
+ if (i.getChecked()) {
+ return (IAndroidTarget) i.getData();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Adds a listener to adjust the columns width when the parent is resized.
+ * <p/>
+ * If we need something more fancy, we might want to use this:
+ * http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet77.java?view=co
+ */
+ private void adjustColumnsWidth(final Table table,
+ final TableColumn column0,
+ final TableColumn column1,
+ final TableColumn column2) {
+ // Add a listener to resize the column to the full width of the table
+ table.addControlListener(new ControlAdapter() {
+ @Override
+ public void controlResized(ControlEvent e) {
+ Rectangle r = table.getClientArea();
+ column0.setWidth(r.width * 3 / 10); // 30%
+ column1.setWidth(r.width * 5 / 10); // 50%
+ column2.setWidth(r.width * 2 / 10); // 20%
+ }
+ });
+ }
+
+
+ /**
+ * Creates a selection listener that will check or uncheck the whole line when
+ * double-clicked (aka "the default selection").
+ */
+ private void setupSelectionListener(final Table table) {
+ // Add a selection listener that will check/uncheck items when they are double-clicked
+ table.addSelectionListener(new SelectionListener() {
+ /** Default selection means double-click on "most" platforms */
+ public void widgetDefaultSelected(SelectionEvent e) {
+ if (e.item instanceof TableItem) {
+ TableItem i = (TableItem) e.item;
+ i.setChecked(!i.getChecked());
+ enforceSingleSelection(i);
+ updateDescription(i);
+ }
+
+ if (mSelectionListener != null) {
+ mSelectionListener.widgetDefaultSelected(e);
+ }
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ if (e.item instanceof TableItem) {
+ TableItem i = (TableItem) e.item;
+ enforceSingleSelection(i);
+ updateDescription(i);
+ }
+
+ if (mSelectionListener != null) {
+ mSelectionListener.widgetSelected(e);
+ }
+ }
+
+ /**
+ * If we're not in multiple selection mode, uncheck all other
+ * items when this one is selected.
+ */
+ private void enforceSingleSelection(TableItem item) {
+ if (!mAllowMultipleSelection && item.getChecked()) {
+ Table parentTable = item.getParent();
+ for (TableItem i2 : parentTable.getItems()) {
+ if (i2 != item && i2.getChecked()) {
+ i2.setChecked(false);
+ }
+ }
+ }
+ }
+ });
+ }
+
+
+ /**
+ * Fills the table with all SDK targets.
+ * The table columns are:
+ * <ul>
+ * <li>column 0: sdk name
+ * <li>column 1: sdk vendor
+ * <li>column 2: sdk api name
+ * </ul>
+ */
+ private void fillTable(final Table table) {
+ if (mTargets != null && mTargets.length > 0) {
+ table.setEnabled(true);
+ for (IAndroidTarget target : mTargets) {
+ TableItem item = new TableItem(table, SWT.NONE);
+ item.setData(target);
+ item.setText(0, target.getName());
+ item.setText(1, target.getVendor());
+ item.setText(2, target.getApiVersionName());
+ }
+ } else {
+ table.setEnabled(false);
+ TableItem item = new TableItem(table, SWT.NONE);
+ item.setData(null);
+ item.setText(0, "--");
+ item.setText(1, "No target available");
+ item.setText(2, "--");
+ }
+ }
+
+ /**
+ * Sets up a tooltip that displays the current item description.
+ * <p/>
+ * Displaying a tooltip over the table looks kind of odd here. Instead we actually
+ * display the description in a label under the table.
+ */
+ private void setupTooltip(final Table table) {
+ /*
+ * Reference:
+ * http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet125.java?view=markup
+ */
+
+ final Listener listener = new Listener() {
+ public void handleEvent(Event event) {
+
+ switch(event.type) {
+ case SWT.KeyDown:
+ case SWT.MouseExit:
+ case SWT.MouseDown:
+ return;
+
+ case SWT.MouseHover:
+ updateDescription(table.getItem(new Point(event.x, event.y)));
+ break;
+
+ case SWT.Selection:
+ if (event.item instanceof TableItem) {
+ updateDescription((TableItem) event.item);
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ }
+ };
+
+ table.addListener(SWT.Dispose, listener);
+ table.addListener(SWT.KeyDown, listener);
+ table.addListener(SWT.MouseMove, listener);
+ table.addListener(SWT.MouseHover, listener);
+ }
+
+ /**
+ * Updates the description label with the description of the item's android target, if any.
+ */
+ private void updateDescription(TableItem item) {
+ if (item != null) {
+ Object data = item.getData();
+ if (data instanceof IAndroidTarget) {
+ String newTooltip = ((IAndroidTarget) data).getDescription();
+ mDescription.setText(newTooltip == null ? "" : newTooltip); //$NON-NLS-1$
+ }
+ }
+ }
+}
diff --git a/tools/traceview/.classpath b/tools/traceview/.classpath
index 6ea87e8..e71cb61 100644
--- a/tools/traceview/.classpath
+++ b/tools/traceview/.classpath
@@ -3,6 +3,6 @@
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/ANDROID_SWT"/>
- <classpathentry combineaccessrules="false" kind="src" path="/PingService"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/SdkStatsService"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/tools/traceview/etc/manifest.txt b/tools/traceview/etc/manifest.txt
index c3c2aec..6cdbc7e 100644
--- a/tools/traceview/etc/manifest.txt
+++ b/tools/traceview/etc/manifest.txt
@@ -1,2 +1,2 @@
-Main-Class: com.google.traceview.MainWindow
+Main-Class: com.android.traceview.MainWindow
Class-Path: swt.jar org.eclipse.equinox.common_3.2.0.v20060603.jar org.eclipse.jface_3.2.0.I20060605-1400.jar org.eclipse.core.commands_3.2.0.I20060605-1400.jar
diff --git a/tools/zoneinfo/ZoneCompactor.java b/tools/zoneinfo/ZoneCompactor.java
new file mode 100644
index 0000000..eea7dd4
--- /dev/null
+++ b/tools/zoneinfo/ZoneCompactor.java
@@ -0,0 +1,158 @@
+
+import java.io.*;
+import java.util.*;
+
+// usage: java ZoneCompiler <setup file> <top-level directory>
+//
+// Compile a set of tzfile-formatted files into a single file plus
+// an index file.
+//
+// The compilation is controlled by a setup file, which is provided as a
+// command-line argument. The setup file has the form:
+//
+// Link <toName> <fromName>
+// ...
+// <zone filename>
+// ...
+//
+// Note that the links must be declared prior to the zone names. A
+// zone name is a filename relative to the source directory such as
+// 'GMT', 'Africa/Dakar', or 'America/Argentina/Jujuy'.
+//
+// Use the 'zic' command-line tool to convert from flat files
+// (e.g., 'africa', 'northamerica') into a suitable source directory
+// hierarchy for this tool (e.g., 'data/Africa/Abidjan').
+//
+// Example:
+// zic -d data tz2007h
+// javac ZoneCompactor.java
+// java ZoneCompactor setup data
+// <produces zoneinfo.dat and zoneinfo.idx>
+
+public class ZoneCompactor {
+
+ // Zone name synonyms
+ Map<String,String> links = new HashMap<String,String>();
+
+ // File starting bytes by zone name
+ Map<String,Integer> starts = new HashMap<String,Integer>();
+
+ // File lengths by zone name
+ Map<String,Integer> lengths = new HashMap<String,Integer>();
+
+ // Raw GMT offsets by zone name
+ Map<String,Integer> offsets = new HashMap<String,Integer>();
+ int start = 0;
+
+ // Maximum number of characters in a zone name, including '\0' terminator
+ private static final int MAXNAME = 40;
+
+ // Concatenate the contents of 'inFile' onto 'out'
+ private static void copyFile(File inFile, OutputStream out)
+ throws Exception {
+ InputStream in = new FileInputStream(inFile);
+ byte[] buf = new byte[8192];
+ while (true) {
+ int nbytes = in.read(buf);
+ if (nbytes == -1) {
+ break;
+ }
+ out.write(buf, 0, nbytes);
+ }
+ out.flush();
+ return;
+ }
+
+ // Write a 32-bit integer in network byte order
+ private void writeInt(OutputStream os, int x) throws IOException {
+ os.write((x >> 24) & 0xff);
+ os.write((x >> 16) & 0xff);
+ os.write((x >> 8) & 0xff);
+ os.write( x & 0xff);
+ }
+
+ public ZoneCompactor(String setupFilename, String dirName)
+ throws Exception {
+ File zoneInfoFile = new File("zoneinfo.dat");
+ zoneInfoFile.delete();
+ OutputStream zoneInfo = new FileOutputStream(zoneInfoFile);
+
+ BufferedReader rdr = new BufferedReader(new FileReader(setupFilename));
+
+ String s;
+ while ((s = rdr.readLine()) != null) {
+ s = s.trim();
+ if (s.startsWith("Link")) {
+ StringTokenizer st = new StringTokenizer(s);
+ st.nextToken();
+ String to = st.nextToken();
+ String from = st.nextToken();
+ links.put(from, to);
+ } else {
+ String link = links.get(s);
+ if (link == null) {
+ File f = new File(dirName, s);
+ long length = f.length();
+ starts.put(s, new Integer(start));
+ lengths.put(s, new Integer((int)length));
+
+ TimeZone tz = TimeZone.getTimeZone(s);
+ int gmtOffset = tz.getRawOffset();
+ offsets.put(s, new Integer(gmtOffset));
+
+ start += length;
+ copyFile(f, zoneInfo);
+ }
+ }
+ }
+ zoneInfo.close();
+
+ // Fill in fields for links
+ Iterator<String> iter = links.keySet().iterator();
+ while (iter.hasNext()) {
+ String from = iter.next();
+ String to = links.get(from);
+
+ starts.put(from, starts.get(to));
+ lengths.put(from, lengths.get(to));
+ offsets.put(from, offsets.get(to));
+ }
+
+ File idxFile = new File("zoneinfo.idx");
+ idxFile.delete();
+ FileOutputStream idx = new FileOutputStream(idxFile);
+
+ ArrayList l = new ArrayList();
+ l.addAll(starts.keySet());
+ Collections.sort(l);
+ Iterator<String> ziter = l.iterator();
+ while (ziter.hasNext()) {
+ String zname = ziter.next();
+ if (zname.length() >= MAXNAME) {
+ System.err.println("Error - zone filename exceeds " +
+ (MAXNAME - 1) + " characters!");
+ }
+
+ byte[] znameBuf = new byte[MAXNAME];
+ for (int i = 0; i < zname.length(); i++) {
+ znameBuf[i] = (byte)zname.charAt(i);
+ }
+ idx.write(znameBuf);
+ writeInt(idx, starts.get(zname).intValue());
+ writeInt(idx, lengths.get(zname).intValue());
+ writeInt(idx, offsets.get(zname).intValue());
+ }
+ idx.close();
+
+ // System.out.println("maxLength = " + maxLength);
+ }
+
+ public static void main(String[] args) throws Exception {
+ if (args.length != 2) {
+ System.err.println("usage: java ZoneCompactor <setup> <data dir>");
+ System.exit(0);
+ }
+ new ZoneCompactor(args[0], args[1]);
+ }
+
+}
diff --git a/tools/zoneinfo/generate b/tools/zoneinfo/generate
new file mode 100755
index 0000000..0b087a8
--- /dev/null
+++ b/tools/zoneinfo/generate
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+version=tzdata2008h
+
+mkdir data
+
+for i in $version/africa \
+ $version/antarctica \
+ $version/asia \
+ $version/australasia \
+ $version/etcetera \
+ $version/europe \
+ $version/factory \
+ $version/northamerica \
+ $version/solar87 \
+ $version/solar88 \
+ $version/solar89 \
+ $version/southamerica
+do
+ zic -d data $i
+done
+
+javac -target 1.5 ZoneCompactor.java
+
+(
+ cat $version/* | grep '^Link' | awk '{print $1, $2, $3}'
+ (
+ cat $version/* | grep '^Zone' | awk '{print $2}'
+ cat $version/* | grep '^Link' | awk '{print $3}'
+ ) | LC_ALL="C" sort
+) | grep -v Riyadh8 > setup
+
+java ZoneCompactor setup data
+
+cp zoneinfo.dat zoneinfo.idx ../../../data/zoneinfo
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/MODULE_LICENSE_EPL b/tools/zoneinfo/tzdata2008h/MODULE_LICENSE_PUBLIC_DOMAIN
similarity index 100%
copy from tools/eclipse/plugins/com.android.ide.eclipse.common/MODULE_LICENSE_EPL
copy to tools/zoneinfo/tzdata2008h/MODULE_LICENSE_PUBLIC_DOMAIN
diff --git a/tools/zoneinfo/tzdata2008h/africa b/tools/zoneinfo/tzdata2008h/africa
new file mode 100644
index 0000000..34a62b9
--- /dev/null
+++ b/tools/zoneinfo/tzdata2008h/africa
@@ -0,0 +1,840 @@
+# @(#)africa 8.17
+# <pre>
+
+# This data is by no means authoritative; if you think you know better,
+# go ahead and edit the file (and please send any changes to
+# tz@elsie.nci.nih.gov for general use in the future).
+
+# From Paul Eggert (2006-03-22):
+#
+# A good source for time zone historical data outside the U.S. is
+# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
+# San Diego: ACS Publications, Inc. (2003).
+#
+# Gwillim Law writes that a good source
+# for recent time zone data is the International Air Transport
+# Association's Standard Schedules Information Manual (IATA SSIM),
+# published semiannually. Law sent in several helpful summaries
+# of the IATA's data after 1990.
+#
+# Except where otherwise noted, Shanks & Pottenger is the source for
+# entries through 1990, and IATA SSIM is the source for entries afterwards.
+#
+# Another source occasionally used is Edward W. Whitman, World Time Differences,
+# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which
+# I found in the UCLA library.
+#
+# A reliable and entertaining source about time zones is
+# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
+#
+# Previous editions of this database used WAT, CAT, SAT, and EAT
+# for +0:00 through +3:00, respectively,
+# but Mark R V Murray reports that
+# `SAST' is the official abbreviation for +2:00 in the country of South Africa,
+# `CAT' is commonly used for +2:00 in countries north of South Africa, and
+# `WAT' is probably the best name for +1:00, as the common phrase for
+# the area that includes Nigeria is ``West Africa''.
+# He has heard of ``Western Sahara Time'' for +0:00 but can find no reference.
+#
+# To make things confusing, `WAT' seems to have been used for -1:00 long ago;
+# I'd guess that this was because people needed _some_ name for -1:00,
+# and at the time, far west Africa was the only major land area in -1:00.
+# This usage is now obsolete, as the last use of -1:00 on the African
+# mainland seems to have been 1976 in Western Sahara.
+#
+# To summarize, the following abbreviations seem to have some currency:
+# -1:00 WAT West Africa Time (no longer used)
+# 0:00 GMT Greenwich Mean Time
+# 2:00 CAT Central Africa Time
+# 2:00 SAST South Africa Standard Time
+# and Murray suggests the following abbreviation:
+# 1:00 WAT West Africa Time
+# I realize that this leads to `WAT' being used for both -1:00 and 1:00
+# for times before 1976, but this is the best I can think of
+# until we get more information.
+#
+# I invented the following abbreviations; corrections are welcome!
+# 2:00 WAST West Africa Summer Time
+# 2:30 BEAT British East Africa Time (no longer used)
+# 2:44:45 BEAUT British East Africa Unified Time (no longer used)
+# 3:00 CAST Central Africa Summer Time (no longer used)
+# 3:00 SAST South Africa Summer Time (no longer used)
+# 3:00 EAT East Africa Time
+# 4:00 EAST East Africa Summer Time (no longer used)
+
+# Algeria
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Algeria 1916 only - Jun 14 23:00s 1:00 S
+Rule Algeria 1916 1919 - Oct Sun>=1 23:00s 0 -
+Rule Algeria 1917 only - Mar 24 23:00s 1:00 S
+Rule Algeria 1918 only - Mar 9 23:00s 1:00 S
+Rule Algeria 1919 only - Mar 1 23:00s 1:00 S
+Rule Algeria 1920 only - Feb 14 23:00s 1:00 S
+Rule Algeria 1920 only - Oct 23 23:00s 0 -
+Rule Algeria 1921 only - Mar 14 23:00s 1:00 S
+Rule Algeria 1921 only - Jun 21 23:00s 0 -
+Rule Algeria 1939 only - Sep 11 23:00s 1:00 S
+Rule Algeria 1939 only - Nov 19 1:00 0 -
+Rule Algeria 1944 1945 - Apr Mon>=1 2:00 1:00 S
+Rule Algeria 1944 only - Oct 8 2:00 0 -
+Rule Algeria 1945 only - Sep 16 1:00 0 -
+Rule Algeria 1971 only - Apr 25 23:00s 1:00 S
+Rule Algeria 1971 only - Sep 26 23:00s 0 -
+Rule Algeria 1977 only - May 6 0:00 1:00 S
+Rule Algeria 1977 only - Oct 21 0:00 0 -
+Rule Algeria 1978 only - Mar 24 1:00 1:00 S
+Rule Algeria 1978 only - Sep 22 3:00 0 -
+Rule Algeria 1980 only - Apr 25 0:00 1:00 S
+Rule Algeria 1980 only - Oct 31 2:00 0 -
+# Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's
+# more precise 0:09:21.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Algiers 0:12:12 - LMT 1891 Mar 15 0:01
+ 0:09:21 - PMT 1911 Mar 11 # Paris Mean Time
+ 0:00 Algeria WE%sT 1940 Feb 25 2:00
+ 1:00 Algeria CE%sT 1946 Oct 7
+ 0:00 - WET 1956 Jan 29
+ 1:00 - CET 1963 Apr 14
+ 0:00 Algeria WE%sT 1977 Oct 21
+ 1:00 Algeria CE%sT 1979 Oct 26
+ 0:00 Algeria WE%sT 1981 May
+ 1:00 - CET
+
+# Angola
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Luanda 0:52:56 - LMT 1892
+ 0:52:04 - AOT 1911 May 26 # Angola Time
+ 1:00 - WAT
+
+# Benin
+# Whitman says they switched to 1:00 in 1946, not 1934;
+# go with Shanks & Pottenger.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Porto-Novo 0:10:28 - LMT 1912
+ 0:00 - GMT 1934 Feb 26
+ 1:00 - WAT
+
+# Botswana
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Gaborone 1:43:40 - LMT 1885
+ 2:00 - CAT 1943 Sep 19 2:00
+ 2:00 1:00 CAST 1944 Mar 19 2:00
+ 2:00 - CAT
+
+# Burkina Faso
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Ouagadougou -0:06:04 - LMT 1912
+ 0:00 - GMT
+
+# Burundi
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Bujumbura 1:57:28 - LMT 1890
+ 2:00 - CAT
+
+# Cameroon
+# Whitman says they switched to 1:00 in 1920; go with Shanks & Pottenger.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Douala 0:38:48 - LMT 1912
+ 1:00 - WAT
+
+# Cape Verde
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Atlantic/Cape_Verde -1:34:04 - LMT 1907 # Praia
+ -2:00 - CVT 1942 Sep
+ -2:00 1:00 CVST 1945 Oct 15
+ -2:00 - CVT 1975 Nov 25 2:00
+ -1:00 - CVT
+
+# Central African Republic
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Bangui 1:14:20 - LMT 1912
+ 1:00 - WAT
+
+# Chad
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Ndjamena 1:00:12 - LMT 1912
+ 1:00 - WAT 1979 Oct 14
+ 1:00 1:00 WAST 1980 Mar 8
+ 1:00 - WAT
+
+# Comoros
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Indian/Comoro 2:53:04 - LMT 1911 Jul # Moroni, Gran Comoro
+ 3:00 - EAT
+
+# Democratic Republic of Congo
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Kinshasa 1:01:12 - LMT 1897 Nov 9
+ 1:00 - WAT
+Zone Africa/Lubumbashi 1:49:52 - LMT 1897 Nov 9
+ 2:00 - CAT
+
+# Republic of the Congo
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Brazzaville 1:01:08 - LMT 1912
+ 1:00 - WAT
+
+# Cote D'Ivoire
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Abidjan -0:16:08 - LMT 1912
+ 0:00 - GMT
+
+# Djibouti
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Djibouti 2:52:36 - LMT 1911 Jul
+ 3:00 - EAT
+
+###############################################################################
+
+# Egypt
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Egypt 1940 only - Jul 15 0:00 1:00 S
+Rule Egypt 1940 only - Oct 1 0:00 0 -
+Rule Egypt 1941 only - Apr 15 0:00 1:00 S
+Rule Egypt 1941 only - Sep 16 0:00 0 -
+Rule Egypt 1942 1944 - Apr 1 0:00 1:00 S
+Rule Egypt 1942 only - Oct 27 0:00 0 -
+Rule Egypt 1943 1945 - Nov 1 0:00 0 -
+Rule Egypt 1945 only - Apr 16 0:00 1:00 S
+Rule Egypt 1957 only - May 10 0:00 1:00 S
+Rule Egypt 1957 1958 - Oct 1 0:00 0 -
+Rule Egypt 1958 only - May 1 0:00 1:00 S
+Rule Egypt 1959 1981 - May 1 1:00 1:00 S
+Rule Egypt 1959 1965 - Sep 30 3:00 0 -
+Rule Egypt 1966 1994 - Oct 1 3:00 0 -
+Rule Egypt 1982 only - Jul 25 1:00 1:00 S
+Rule Egypt 1983 only - Jul 12 1:00 1:00 S
+Rule Egypt 1984 1988 - May 1 1:00 1:00 S
+Rule Egypt 1989 only - May 6 1:00 1:00 S
+Rule Egypt 1990 1994 - May 1 1:00 1:00 S
+# IATA (after 1990) says transitions are at 0:00.
+# Go with IATA starting in 1995, except correct 1995 entry from 09-30 to 09-29.
+Rule Egypt 1995 max - Apr lastFri 0:00s 1:00 S
+Rule Egypt 1995 2005 - Sep lastThu 23:00s 0 -
+# From Steffen Thorsen (2006-09-19):
+# The Egyptian Gazette, issue 41,090 (2006-09-18), page 1, reports:
+# Egypt will turn back clocks by one hour at the midnight of Thursday
+# after observing the daylight saving time since May.
+# http://news.gom.com.eg/gazette/pdf/2006/09/18/01.pdf
+Rule Egypt 2006 only - Sep 21 23:00s 0 -
+# From Dirk Losch (2007-08-14):
+# I received a mail from an airline which says that the daylight
+# saving time in Egypt will end in the night of 2007-09-06 to 2007-09-07.
+# From Jesper Norgaard Welen (2007-08-15): [The following agree:]
+# http://www.nentjes.info/Bill/bill5.htm
+# http://www.timeanddate.com/worldclock/city.html?n=53
+# From Steffen Thorsen (2007-09-04): The official information...:
+# http://www.sis.gov.eg/En/EgyptOnline/Miscellaneous/000002/0207000000000000001580.htm
+Rule Egypt 2007 only - Sep Thu>=1 23:00s 0 -
+# From Abdelrahman Hassan (2007-09-06):
+# Due to the Hijri (lunar Islamic calendar) year being 11 days shorter
+# than the year of the Gregorian calendar, Ramadan shifts earlier each
+# year. This year it will be observed September 13 (September is quite
+# hot in Egypt), and the idea is to make fasting easier for workers by
+# shifting business hours one hour out of daytime heat. Consequently,
+# unless discontinued, next DST may end Thursday 28 August 2008.
+# From Paul Eggert (2007-08-17):
+# For lack of better info, assume the new rule is last Thursday in August.
+Rule Egypt 2008 max - Aug lastThu 23:00s 0 -
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Cairo 2:05:00 - LMT 1900 Oct
+ 2:00 Egypt EE%sT
+
+# Equatorial Guinea
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Malabo 0:35:08 - LMT 1912
+ 0:00 - GMT 1963 Dec 15
+ 1:00 - WAT
+
+# Eritrea
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Asmara 2:35:32 - LMT 1870
+ 2:35:32 - AMT 1890 # Asmara Mean Time
+ 2:35:20 - ADMT 1936 May 5 # Adis Dera MT
+ 3:00 - EAT
+
+# Ethiopia
+# From Paul Eggert (2006-03-22):
+# Shanks & Pottenger write that Ethiopia had six narrowly-spaced time zones
+# between 1870 and 1890, and that they merged to 38E50 (2:35:20) in 1890.
+# We'll guess that 38E50 is for Adis Dera.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Addis_Ababa 2:34:48 - LMT 1870
+ 2:35:20 - ADMT 1936 May 5 # Adis Dera MT
+ 3:00 - EAT
+
+# Gabon
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Libreville 0:37:48 - LMT 1912
+ 1:00 - WAT
+
+# Gambia
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Banjul -1:06:36 - LMT 1912
+ -1:06:36 - BMT 1935 # Banjul Mean Time
+ -1:00 - WAT 1964
+ 0:00 - GMT
+
+# Ghana
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+# Whitman says DST was observed from 1931 to ``the present'';
+# go with Shanks & Pottenger.
+Rule Ghana 1936 1942 - Sep 1 0:00 0:20 GHST
+Rule Ghana 1936 1942 - Dec 31 0:00 0 GMT
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Accra -0:00:52 - LMT 1918
+ 0:00 Ghana %s
+
+# Guinea
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Conakry -0:54:52 - LMT 1912
+ 0:00 - GMT 1934 Feb 26
+ -1:00 - WAT 1960
+ 0:00 - GMT
+
+# Guinea-Bissau
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Bissau -1:02:20 - LMT 1911 May 26
+ -1:00 - WAT 1975
+ 0:00 - GMT
+
+# Kenya
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Nairobi 2:27:16 - LMT 1928 Jul
+ 3:00 - EAT 1930
+ 2:30 - BEAT 1940
+ 2:44:45 - BEAUT 1960
+ 3:00 - EAT
+
+# Lesotho
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Maseru 1:50:00 - LMT 1903 Mar
+ 2:00 - SAST 1943 Sep 19 2:00
+ 2:00 1:00 SAST 1944 Mar 19 2:00
+ 2:00 - SAST
+
+# Liberia
+# From Paul Eggert (2006-03-22):
+# In 1972 Liberia was the last country to switch
+# from a UTC offset that was not a multiple of 15 or 20 minutes.
+# Howse reports that it was in honor of their president's birthday.
+# Shank & Pottenger report the date as May 1, whereas Howse reports Jan;
+# go with Shanks & Pottenger.
+# For Liberia before 1972, Shanks & Pottenger report -0:44, whereas Howse and
+# Whitman each report -0:44:30; go with the more precise figure.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Monrovia -0:43:08 - LMT 1882
+ -0:43:08 - MMT 1919 Mar # Monrovia Mean Time
+ -0:44:30 - LRT 1972 May # Liberia Time
+ 0:00 - GMT
+
+###############################################################################
+
+# Libya
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Libya 1951 only - Oct 14 2:00 1:00 S
+Rule Libya 1952 only - Jan 1 0:00 0 -
+Rule Libya 1953 only - Oct 9 2:00 1:00 S
+Rule Libya 1954 only - Jan 1 0:00 0 -
+Rule Libya 1955 only - Sep 30 0:00 1:00 S
+Rule Libya 1956 only - Jan 1 0:00 0 -
+Rule Libya 1982 1984 - Apr 1 0:00 1:00 S
+Rule Libya 1982 1985 - Oct 1 0:00 0 -
+Rule Libya 1985 only - Apr 6 0:00 1:00 S
+Rule Libya 1986 only - Apr 4 0:00 1:00 S
+Rule Libya 1986 only - Oct 3 0:00 0 -
+Rule Libya 1987 1989 - Apr 1 0:00 1:00 S
+Rule Libya 1987 1989 - Oct 1 0:00 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Tripoli 0:52:44 - LMT 1920
+ 1:00 Libya CE%sT 1959
+ 2:00 - EET 1982
+ 1:00 Libya CE%sT 1990 May 4
+# The following entries are from Shanks & Pottenger;
+# the IATA SSIM data contain some obvious errors.
+ 2:00 - EET 1996 Sep 30
+ 1:00 - CET 1997 Apr 4
+ 1:00 1:00 CEST 1997 Oct 4
+ 2:00 - EET
+
+# Madagascar
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Indian/Antananarivo 3:10:04 - LMT 1911 Jul
+ 3:00 - EAT 1954 Feb 27 23:00s
+ 3:00 1:00 EAST 1954 May 29 23:00s
+ 3:00 - EAT
+
+# Malawi
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Blantyre 2:20:00 - LMT 1903 Mar
+ 2:00 - CAT
+
+# Mali
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Bamako -0:32:00 - LMT 1912
+ 0:00 - GMT 1934 Feb 26
+ -1:00 - WAT 1960 Jun 20
+ 0:00 - GMT
+
+# Mauritania
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Nouakchott -1:03:48 - LMT 1912
+ 0:00 - GMT 1934 Feb 26
+ -1:00 - WAT 1960 Nov 28
+ 0:00 - GMT
+
+# Mauritius
+
+# From Steffen Thorsen (2008-06-25):
+# Mauritius plans to observe DST from 2008-11-01 to 2009-03-31 on a trial
+# basis....
+# It seems that Mauritius observed daylight saving time from 1982-10-10 to
+# 1983-03-20 as well, but that was not successful....
+# http://www.timeanddate.com/news/time/mauritius-daylight-saving-time.html
+
+# From Alex Krivenyshev (2008-06-25):
+# http://economicdevelopment.gov.mu/portal/site/Mainhomepage/menuitem.a42b24128104d9845dabddd154508a0c/?content_id=0a7cee8b5d69a110VgnVCM1000000a04a8c0RCRD
+
+# From Arthur David Olson (2008-06-30):
+# The www.timeanddate.com article cited by Steffen Thorsen notes that "A
+# final decision has yet to be made on the times that daylight saving
+# would begin and end on these dates." As a place holder, use midnight.
+
+# From Paul Eggert (2008-06-30):
+# Follow Thorsen on DST in 1982/1983, instead of Shanks & Pottenger.
+
+# From Steffen Thorsen (2008-07-10):
+# According to
+# <a href="http://www.lexpress.mu/display_article.php?news_id=111216">
+# http://www.lexpress.mu/display_article.php?news_id=111216
+# </a>
+# (in French), Mauritius will start and end their DST a few days earlier
+# than previously announced (2008-11-01 to 2009-03-31). The new start
+# date is 2008-10-26 at 02:00 and the new end date is 2009-03-27 (no time
+# given, but it is probably at either 2 or 3 wall clock time).
+#
+# A little strange though, since the article says that they moved the date
+# to align itself with Europe and USA which also change time on that date,
+# but that means they have not paid attention to what happened in
+# USA/Canada last year (DST ends first Sunday in November). I also wonder
+# why that they end on a Friday, instead of aligning with Europe which
+# changes two days later.
+
+# From Alex Krivenyshev (2008-07-11):
+# Seems that English language article "The revival of daylight saving
+# time: Energy conservation?"-# No. 16578 (07/11/2008) was originally
+# published on Monday, June 30, 2008...
+#
+# I guess that article in French "Le gouvernement avance l'introduction
+# de l'heure d'ete" stating that DST in Mauritius starting on October 26
+# and ending on March 27, 2009 is the most recent one.
+# ...
+# <a href="http://www.worldtimezone.com/dst_news/dst_news_mauritius02.html">
+# http://www.worldtimezone.com/dst_news/dst_news_mauritius02.html
+# </a>
+
+# From Riad M. Hossen Ally (2008-08-03):
+# The Government of Mauritius weblink
+# <a href="http://www.gov.mu/portal/site/pmosite/menuitem.4ca0efdee47462e7440a600248a521ca/?content_id=3D4728ca68b2a5b110VgnVCM1000000a04a8c0RCRD">
+# http://www.gov.mu/portal/site/pmosite/menuitem.4ca0efdee47462e7440a600248a521ca/?content_id=3D4728ca68b2a5b110VgnVCM1000000a04a8c0RCRD
+# </a>
+# Cabinet Decision of July 18th, 2008 states as follows:
+#
+# 4. ...Cabinet has agreed to the introduction into the National Assembly
+# of the Time Bill which provides for the introduction of summer time in
+# Mauritius. The summer time period which will be of one hour ahead of
+# the standard time, will be aligned with that in Europe and the United
+# States of America. It will start at two o'clock in the morning on the
+# last Sunday of October and will end at two o'clock in the morning on
+# the last Sunday of March the following year. The summer time for the
+# year 2008 - 2009 will, therefore, be effective as from 26 October 2008
+# and end on 29 March 2009.
+
+# From Ed Maste (2008-10-07):
+# THE TIME BILL (No. XXVII of 2008) Explanatory Memorandum states the
+# beginning / ending of summer time is 2 o'clock standard time in the
+# morning of the last Sunday of October / last Sunday of March.
+# <a href="http://www.gov.mu/portal/goc/assemblysite/file/bill2708.pdf">
+# http://www.gov.mu/portal/goc/assemblysite/file/bill2708.pdf
+# </a>
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Mauritius 1982 only - Oct 10 0:00 1:00 S
+Rule Mauritius 1983 only - Mar 21 0:00 0 -
+Rule Mauritius 2008 max - Oct lastSun 2:00s 1:00 S
+Rule Mauritius 2009 max - Mar lastSun 2:00s 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Indian/Mauritius 3:50:00 - LMT 1907 # Port Louis
+ 4:00 Mauritius MU%sT # Mauritius Time
+# Agalega Is, Rodriguez
+# no information; probably like Indian/Mauritius
+
+# Mayotte
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Indian/Mayotte 3:00:56 - LMT 1911 Jul # Mamoutzou
+ 3:00 - EAT
+
+# Morocco
+# See the `europe' file for Spanish Morocco (Africa/Ceuta).
+
+# From Alex Krivenyshev (2008-05-09):
+# Here is an article that Morocco plan to introduce Daylight Saving Time between
+# 1 June, 2008 and 27 September, 2008.
+#
+# "... Morocco is to save energy by adjusting its clock during summer so it will
+# be one hour ahead of GMT between 1 June and 27 September, according to
+# Communication Minister and Gov ernment Spokesman, Khalid Naciri...."
+#
+# <a href="http://www.worldtimezone.net/dst_news/dst_news_morocco01.html">
+# http://www.worldtimezone.net/dst_news/dst_news_morocco01.html
+# </a>
+# OR
+# <a href="http://en.afrik.com/news11892.html">
+# http://en.afrik.com/news11892.html
+# </a>
+
+# From Alex Krivenyshev (2008-05-09):
+# The Morocco time change can be confirmed on Morocco web site Maghreb Arabe Presse:
+# <a href="http://www.map.ma/eng/sections/box3/morocco_shifts_to_da/view">
+# http://www.map.ma/eng/sections/box3/morocco_shifts_to_da/view
+# </a>
+#
+# Morocco shifts to daylight time on June 1st through September 27, Govt.
+# spokesman.
+
+# From Patrice Scattolin (2008-05-09):
+# According to this article:
+# <a href="http://www.avmaroc.com/actualite/heure-dete-comment-a127896.html">
+# http://www.avmaroc.com/actualite/heure-dete-comment-a127896.html
+# </a>
+# (and republished here:
+# <a href="http://www.actu.ma/heure-dete-comment_i127896_0.html">
+# http://www.actu.ma/heure-dete-comment_i127896_0.html
+# </a>
+# )
+# the changes occurs at midnight:
+#
+# saturday night may 31st at midnight (which in french is to be
+# intrepreted as the night between saturday and sunday)
+# sunday night the 28th at midnight
+#
+# Seeing that the 28th is monday, I am guessing that she intends to say
+# the midnight of the 28th which is the midnight between sunday and
+# monday, which jives with other sources that say that it's inclusive
+# june1st to sept 27th.
+#
+# The decision was taken by decree *2-08-224 *but I can't find the decree
+# published on the web.
+#
+# It's also confirmed here:
+# <a href="http://www.maroc.ma/NR/exeres/FACF141F-D910-44B0-B7FA-6E03733425D1.htm">
+# http://www.maroc.ma/NR/exeres/FACF141F-D910-44B0-B7FA-6E03733425D1.htm
+# </a>
+# on a government portal as being between june 1st and sept 27th (not yet
+# posted in english).
+#
+# The following google query will generate many relevant hits:
+# <a href="http://www.google.com/search?hl=en&q=Conseil+de+gouvernement+maroc+heure+avance&btnG=Search">
+# http://www.google.com/search?hl=en&q=Conseil+de+gouvernement+maroc+heure+avance&btnG=Search
+# </a>
+
+# From Alex Krivenyshev (2008-05-09):
+# Is Western Sahara (part which administrated by Morocco) going to follow
+# Morocco DST changes? Any information? What about other part of
+# Western Sahara - under administration of POLISARIO Front (also named
+# SADR Saharawi Arab Democratic Republic)?
+
+# From Arthur David Olson (2008-05-09):
+# XXX--guess that it is only Morocco for now; guess only 2008 for now.
+
+# From Steffen Thorsen (2008-08-27):
+# Morocco will change the clocks back on the midnight between August 31
+# and September 1. They originally planned to observe DST to near the end
+# of September:
+#
+# One article about it (in French):
+# <a href="http://www.menara.ma/fr/Actualites/Maroc/Societe/ci.retour_a_l_heure_gmt_a_partir_du_dimanche_31_aout_a_minuit_officiel_.default">
+# http://www.menara.ma/fr/Actualites/Maroc/Societe/ci.retour_a_l_heure_gmt_a_partir_du_dimanche_31_aout_a_minuit_officiel_.default
+# </a>
+#
+# We have some further details posted here:
+# <a href="http://www.timeanddate.com/news/time/morocco-ends-dst-early-2008.html">
+# http://www.timeanddate.com/news/time/morocco-ends-dst-early-2008.html
+# </a>
+# RULE NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+
+Rule Morocco 1939 only - Sep 12 0:00 1:00 S
+Rule Morocco 1939 only - Nov 19 0:00 0 -
+Rule Morocco 1940 only - Feb 25 0:00 1:00 S
+Rule Morocco 1945 only - Nov 18 0:00 0 -
+Rule Morocco 1950 only - Jun 11 0:00 1:00 S
+Rule Morocco 1950 only - Oct 29 0:00 0 -
+Rule Morocco 1967 only - Jun 3 12:00 1:00 S
+Rule Morocco 1967 only - Oct 1 0:00 0 -
+Rule Morocco 1974 only - Jun 24 0:00 1:00 S
+Rule Morocco 1974 only - Sep 1 0:00 0 -
+Rule Morocco 1976 1977 - May 1 0:00 1:00 S
+Rule Morocco 1976 only - Aug 1 0:00 0 -
+Rule Morocco 1977 only - Sep 28 0:00 0 -
+Rule Morocco 1978 only - Jun 1 0:00 1:00 S
+Rule Morocco 1978 only - Aug 4 0:00 0 -
+Rule Morocco 2008 only - Jun 1 0:00 1:00 S
+Rule Morocco 2008 only - Sep 1 0:00 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Casablanca -0:30:20 - LMT 1913 Oct 26
+ 0:00 Morocco WE%sT 1984 Mar 16
+ 1:00 - CET 1986
+ 0:00 Morocco WE%sT
+# Western Sahara
+Zone Africa/El_Aaiun -0:52:48 - LMT 1934 Jan
+ -1:00 - WAT 1976 Apr 14
+ 0:00 - WET
+
+# Mozambique
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Maputo 2:10:20 - LMT 1903 Mar
+ 2:00 - CAT
+
+# Namibia
+# The 1994-04-03 transition is from Shanks & Pottenger.
+# Shanks & Pottenger report no DST after 1998-04; go with IATA.
+
+# From Petronella Sibeene (2007-03-30) in
+# <http://allafrica.com/stories/200703300178.html>:
+# While the entire country changes its time, Katima Mulilo and other
+# settlements in Caprivi unofficially will not because the sun there
+# rises and sets earlier compared to other regions. Chief of
+# Forecasting Riaan van Zyl explained that the far eastern parts of
+# the country are close to 40 minutes earlier in sunrise than the rest
+# of the country.
+#
+# From Paul Eggert (2007-03-31):
+# Apparently the Caprivi Strip informally observes Botswana time, but
+# we have no details. In the meantime people there can use Africa/Gaborone.
+
+# RULE NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Namibia 1994 max - Sep Sun>=1 2:00 1:00 S
+Rule Namibia 1995 max - Apr Sun>=1 2:00 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Windhoek 1:08:24 - LMT 1892 Feb 8
+ 1:30 - SWAT 1903 Mar # SW Africa Time
+ 2:00 - SAST 1942 Sep 20 2:00
+ 2:00 1:00 SAST 1943 Mar 21 2:00
+ 2:00 - SAST 1990 Mar 21 # independence
+ 2:00 - CAT 1994 Apr 3
+ 1:00 Namibia WA%sT
+
+# Niger
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Niamey 0:08:28 - LMT 1912
+ -1:00 - WAT 1934 Feb 26
+ 0:00 - GMT 1960
+ 1:00 - WAT
+
+# Nigeria
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Lagos 0:13:36 - LMT 1919 Sep
+ 1:00 - WAT
+
+# Reunion
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Indian/Reunion 3:41:52 - LMT 1911 Jun # Saint-Denis
+ 4:00 - RET # Reunion Time
+#
+# Scattered Islands (Iles Eparses) administered from Reunion are as follows.
+# The following information about them is taken from
+# Iles Eparses (www.outre-mer.gouv.fr/domtom/ile.htm, 1997-07-22, in French;
+# no longer available as of 1999-08-17).
+# We have no info about their time zone histories.
+#
+# Bassas da India - uninhabited
+# Europa Island - inhabited from 1905 to 1910 by two families
+# Glorioso Is - inhabited until at least 1958
+# Juan de Nova - uninhabited
+# Tromelin - inhabited until at least 1958
+
+# Rwanda
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Kigali 2:00:16 - LMT 1935 Jun
+ 2:00 - CAT
+
+# St Helena
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Atlantic/St_Helena -0:22:48 - LMT 1890 # Jamestown
+ -0:22:48 - JMT 1951 # Jamestown Mean Time
+ 0:00 - GMT
+# The other parts of the St Helena territory are similar:
+# Tristan da Cunha: on GMT, say Whitman and the CIA
+# Ascension: on GMT, says usno1995 and the CIA
+# Gough (scientific station since 1955; sealers wintered previously):
+# on GMT, says the CIA
+# Inaccessible, Nightingale: no information, but probably GMT
+
+# Sao Tome and Principe
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Sao_Tome 0:26:56 - LMT 1884
+ -0:36:32 - LMT 1912 # Lisbon Mean Time
+ 0:00 - GMT
+
+# Senegal
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Dakar -1:09:44 - LMT 1912
+ -1:00 - WAT 1941 Jun
+ 0:00 - GMT
+
+# Seychelles
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Indian/Mahe 3:41:48 - LMT 1906 Jun # Victoria
+ 4:00 - SCT # Seychelles Time
+# From Paul Eggert (2001-05-30):
+# Aldabra, Farquhar, and Desroches, originally dependencies of the
+# Seychelles, were transferred to the British Indian Ocean Territory
+# in 1965 and returned to Seychelles control in 1976. We don't know
+# whether this affected their time zone, so omit this for now.
+# Possibly the islands were uninhabited.
+
+# Sierra Leone
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+# Whitman gives Mar 31 - Aug 31 for 1931 on; go with Shanks & Pottenger.
+Rule SL 1935 1942 - Jun 1 0:00 0:40 SLST
+Rule SL 1935 1942 - Oct 1 0:00 0 WAT
+Rule SL 1957 1962 - Jun 1 0:00 1:00 SLST
+Rule SL 1957 1962 - Sep 1 0:00 0 GMT
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Freetown -0:53:00 - LMT 1882
+ -0:53:00 - FMT 1913 Jun # Freetown Mean Time
+ -1:00 SL %s 1957
+ 0:00 SL %s
+
+# Somalia
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Mogadishu 3:01:28 - LMT 1893 Nov
+ 3:00 - EAT 1931
+ 2:30 - BEAT 1957
+ 3:00 - EAT
+
+# South Africa
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule SA 1942 1943 - Sep Sun>=15 2:00 1:00 -
+Rule SA 1943 1944 - Mar Sun>=15 2:00 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Johannesburg 1:52:00 - LMT 1892 Feb 8
+ 1:30 - SAST 1903 Mar
+ 2:00 SA SAST
+# Marion and Prince Edward Is
+# scientific station since 1947
+# no information
+
+# Sudan
+#
+# From <a href="http://www.sunanews.net/sn13jane.html">
+# Sudan News Agency (2000-01-13)
+# </a>, also reported by Michael De Beukelaer-Dossche via Steffen Thorsen:
+# Clocks will be moved ahead for 60 minutes all over the Sudan as of noon
+# Saturday.... This was announced Thursday by Caretaker State Minister for
+# Manpower Abdul-Rahman Nur-Eddin.
+#
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Sudan 1970 only - May 1 0:00 1:00 S
+Rule Sudan 1970 1985 - Oct 15 0:00 0 -
+Rule Sudan 1971 only - Apr 30 0:00 1:00 S
+Rule Sudan 1972 1985 - Apr lastSun 0:00 1:00 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Khartoum 2:10:08 - LMT 1931
+ 2:00 Sudan CA%sT 2000 Jan 15 12:00
+ 3:00 - EAT
+
+# Swaziland
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Mbabane 2:04:24 - LMT 1903 Mar
+ 2:00 - SAST
+
+# Tanzania
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Dar_es_Salaam 2:37:08 - LMT 1931
+ 3:00 - EAT 1948
+ 2:44:45 - BEAUT 1961
+ 3:00 - EAT
+
+# Togo
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Lome 0:04:52 - LMT 1893
+ 0:00 - GMT
+
+# Tunisia
+
+# From Gwillim Law (2005-04-30):
+# My correspondent, Risto Nykanen, has alerted me to another adoption of DST,
+# this time in Tunisia. According to Yahoo France News
+# <http://fr.news.yahoo.com/050426/5/4dumk.html>, in a story attributed to AP
+# and dated 2005-04-26, "Tunisia has decided to advance its official time by
+# one hour, starting on Sunday, May 1. Henceforth, Tunisian time will be
+# UTC+2 instead of UTC+1. The change will take place at 23:00 UTC next
+# Saturday." (My translation)
+#
+# From Oscar van Vlijmen (2005-05-02):
+# LaPresse, the first national daily newspaper ...
+# <http://www.lapresse.tn/archives/archives280405/actualites/lheure.html>
+# ... DST for 2005: on: Sun May 1 0h standard time, off: Fri Sept. 30,
+# 1h standard time.
+#
+# From Atef Loukil (2006-03-28):
+# The daylight saving time will be the same each year:
+# Beginning : the last Sunday of March at 02:00
+# Ending : the last Sunday of October at 03:00 ...
+# http://www.tap.info.tn/en/index.php?option=com_content&task=view&id=1188&Itemid=50
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Tunisia 1939 only - Apr 15 23:00s 1:00 S
+Rule Tunisia 1939 only - Nov 18 23:00s 0 -
+Rule Tunisia 1940 only - Feb 25 23:00s 1:00 S
+Rule Tunisia 1941 only - Oct 6 0:00 0 -
+Rule Tunisia 1942 only - Mar 9 0:00 1:00 S
+Rule Tunisia 1942 only - Nov 2 3:00 0 -
+Rule Tunisia 1943 only - Mar 29 2:00 1:00 S
+Rule Tunisia 1943 only - Apr 17 2:00 0 -
+Rule Tunisia 1943 only - Apr 25 2:00 1:00 S
+Rule Tunisia 1943 only - Oct 4 2:00 0 -
+Rule Tunisia 1944 1945 - Apr Mon>=1 2:00 1:00 S
+Rule Tunisia 1944 only - Oct 8 0:00 0 -
+Rule Tunisia 1945 only - Sep 16 0:00 0 -
+Rule Tunisia 1977 only - Apr 30 0:00s 1:00 S
+Rule Tunisia 1977 only - Sep 24 0:00s 0 -
+Rule Tunisia 1978 only - May 1 0:00s 1:00 S
+Rule Tunisia 1978 only - Oct 1 0:00s 0 -
+Rule Tunisia 1988 only - Jun 1 0:00s 1:00 S
+Rule Tunisia 1988 1990 - Sep lastSun 0:00s 0 -
+Rule Tunisia 1989 only - Mar 26 0:00s 1:00 S
+Rule Tunisia 1990 only - May 1 0:00s 1:00 S
+Rule Tunisia 2005 only - May 1 0:00s 1:00 S
+Rule Tunisia 2005 only - Sep 30 1:00s 0 -
+Rule Tunisia 2006 max - Mar lastSun 2:00s 1:00 S
+Rule Tunisia 2006 max - Oct lastSun 2:00s 0 -
+# Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's
+# more precise 0:09:21.
+# Shanks & Pottenger say the 1911 switch was on Mar 9; go with Howse's Mar 11.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Tunis 0:40:44 - LMT 1881 May 12
+ 0:09:21 - PMT 1911 Mar 11 # Paris Mean Time
+ 1:00 Tunisia CE%sT
+
+# Uganda
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Kampala 2:09:40 - LMT 1928 Jul
+ 3:00 - EAT 1930
+ 2:30 - BEAT 1948
+ 2:44:45 - BEAUT 1957
+ 3:00 - EAT
+
+# Zambia
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Lusaka 1:53:08 - LMT 1903 Mar
+ 2:00 - CAT
+
+# Zimbabwe
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Africa/Harare 2:04:12 - LMT 1903 Mar
+ 2:00 - CAT
diff --git a/tools/zoneinfo/tzdata2008h/antarctica b/tools/zoneinfo/tzdata2008h/antarctica
new file mode 100644
index 0000000..ef279cb
--- /dev/null
+++ b/tools/zoneinfo/tzdata2008h/antarctica
@@ -0,0 +1,327 @@
+# @(#)antarctica 8.4
+# <pre>
+
+# From Paul Eggert (1999-11-15):
+# To keep things manageable, we list only locations occupied year-round; see
+# <a href="http://www.comnap.aq/comnap/comnap.nsf/P/Stations/">
+# COMNAP - Stations and Bases
+# </a>
+# and
+# <a href="http://www.spri.cam.ac.uk/bob/periant.htm">
+# Summary of the Peri-Antarctic Islands (1998-07-23)
+# </a>
+# for information.
+# Unless otherwise specified, we have no time zone information.
+#
+# Except for the French entries,
+# I made up all time zone abbreviations mentioned here; corrections welcome!
+# FORMAT is `zzz' and GMTOFF is 0 for locations while uninhabited.
+
+# These rules are stolen from the `europe' file.
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule RussAQ 1981 1984 - Apr 1 0:00 1:00 S
+Rule RussAQ 1981 1983 - Oct 1 0:00 0 -
+Rule RussAQ 1984 1991 - Sep lastSun 2:00s 0 -
+Rule RussAQ 1985 1991 - Mar lastSun 2:00s 1:00 S
+Rule RussAQ 1992 only - Mar lastSat 23:00 1:00 S
+Rule RussAQ 1992 only - Sep lastSat 23:00 0 -
+Rule RussAQ 1993 max - Mar lastSun 2:00s 1:00 S
+Rule RussAQ 1993 1995 - Sep lastSun 2:00s 0 -
+Rule RussAQ 1996 max - Oct lastSun 2:00s 0 -
+
+# These rules are stolen from the `southamerica' file.
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule ArgAQ 1964 1966 - Mar 1 0:00 0 -
+Rule ArgAQ 1964 1966 - Oct 15 0:00 1:00 S
+Rule ArgAQ 1967 only - Apr 2 0:00 0 -
+Rule ArgAQ 1967 1968 - Oct Sun>=1 0:00 1:00 S
+Rule ArgAQ 1968 1969 - Apr Sun>=1 0:00 0 -
+Rule ArgAQ 1974 only - Jan 23 0:00 1:00 S
+Rule ArgAQ 1974 only - May 1 0:00 0 -
+Rule ChileAQ 1972 1986 - Mar Sun>=9 3:00u 0 -
+Rule ChileAQ 1974 1987 - Oct Sun>=9 4:00u 1:00 S
+Rule ChileAQ 1987 only - Apr 12 3:00u 0 -
+Rule ChileAQ 1988 1989 - Mar Sun>=9 3:00u 0 -
+Rule ChileAQ 1988 only - Oct Sun>=1 4:00u 1:00 S
+Rule ChileAQ 1989 only - Oct Sun>=9 4:00u 1:00 S
+Rule ChileAQ 1990 only - Mar 18 3:00u 0 -
+Rule ChileAQ 1990 only - Sep 16 4:00u 1:00 S
+Rule ChileAQ 1991 1996 - Mar Sun>=9 3:00u 0 -
+Rule ChileAQ 1991 1997 - Oct Sun>=9 4:00u 1:00 S
+Rule ChileAQ 1997 only - Mar 30 3:00u 0 -
+Rule ChileAQ 1998 only - Mar Sun>=9 3:00u 0 -
+Rule ChileAQ 1998 only - Sep 27 4:00u 1:00 S
+Rule ChileAQ 1999 only - Apr 4 3:00u 0 -
+Rule ChileAQ 1999 max - Oct Sun>=9 4:00u 1:00 S
+Rule ChileAQ 2000 max - Mar Sun>=9 3:00u 0 -
+
+
+# Argentina - year-round bases
+# Belgrano II, Confin Coast, -770227-0343737, since 1972-02-05
+# Esperanza, San Martin Land, -6323-05659, since 1952-12-17
+# Jubany, Potter Peninsula, King George Island, -6414-0602320, since 1982-01
+# Marambio, Seymour I, -6414-05637, since 1969-10-29
+# Orcadas, Laurie I, -6016-04444, since 1904-02-22
+# San Martin, Debenham I, -6807-06708, since 1951-03-21
+# (except 1960-03 / 1976-03-21)
+
+# Australia - territories
+# Heard Island, McDonald Islands (uninhabited)
+# previously sealers and scientific personnel wintered
+# <a href="http://web.archive.org/web/20021204222245/http://www.dstc.qut.edu.au/DST/marg/daylight.html">
+# Margaret Turner reports
+# </a> (1999-09-30) that they're UTC+5, with no DST;
+# presumably this is when they have visitors.
+#
+# year-round bases
+# Casey, Bailey Peninsula, -6617+11032, since 1969
+# Davis, Vestfold Hills, -6835+07759, since 1957-01-13
+# (except 1964-11 - 1969-02)
+# Mawson, Holme Bay, -6736+06253, since 1954-02-13
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Antarctica/Casey 0 - zzz 1969
+ 8:00 - WST # Western (Aus) Standard Time
+Zone Antarctica/Davis 0 - zzz 1957 Jan 13
+ 7:00 - DAVT 1964 Nov # Davis Time
+ 0 - zzz 1969 Feb
+ 7:00 - DAVT
+Zone Antarctica/Mawson 0 - zzz 1954 Feb 13
+ 6:00 - MAWT # Mawson Time
+# References:
+# <a href="http://www.antdiv.gov.au/aad/exop/sfo/casey/casey_aws.html">
+# Casey Weather (1998-02-26)
+# </a>
+# <a href="http://www.antdiv.gov.au/aad/exop/sfo/davis/video.html">
+# Davis Station, Antarctica (1998-02-26)
+# </a>
+# <a href="http://www.antdiv.gov.au/aad/exop/sfo/mawson/video.html">
+# Mawson Station, Antarctica (1998-02-25)
+# </a>
+
+# Brazil - year-round base
+# Comandante Ferraz, King George Island, -6205+05824, since 1983/4
+
+# Chile - year-round bases and towns
+# Escudero, South Shetland Is, -621157-0585735, since 1994
+# Presidente Eduadro Frei, King George Island, -6214-05848, since 1969-03-07
+# General Bernardo O'Higgins, Antarctic Peninsula, -6319-05704, since 1948-02
+# Capitan Arturo Prat, -6230-05941
+# Villa Las Estrellas (a town), around the Frei base, since 1984-04-09
+# These locations have always used Santiago time; use TZ='America/Santiago'.
+
+# China - year-round bases
+# Great Wall, King George Island, -6213-05858, since 1985-02-20
+# Zhongshan, Larsemann Hills, Prydz Bay, -6922+07623, since 1989-02-26
+
+# France - year-round bases
+#
+# From Antoine Leca (1997-01-20):
+# Time data are from Nicole Pailleau at the IFRTP
+# (French Institute for Polar Research and Technology).
+# She confirms that French Southern Territories and Terre Adelie bases
+# don't observe daylight saving time, even if Terre Adelie supplies came
+# from Tasmania.
+#
+# French Southern Territories with year-round inhabitants
+#
+# Martin-de-Vivies Base, Amsterdam Island, -374105+0773155, since 1950
+# Alfred-Faure Base, Crozet Islands, -462551+0515152, since 1964
+# Port-aux-Francais, Kerguelen Islands, -492110+0701303, since 1951;
+# whaling & sealing station operated 1908/1914, 1920/1929, and 1951/1956
+#
+# St Paul Island - near Amsterdam, uninhabited
+# fishing stations operated variously 1819/1931
+#
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Indian/Kerguelen 0 - zzz 1950 # Port-aux-Francais
+ 5:00 - TFT # ISO code TF Time
+#
+# year-round base in the main continent
+# Dumont-d'Urville, Ile des Petrels, -6640+14001, since 1956-11
+#
+# Another base at Port-Martin, 50km east, began operation in 1947.
+# It was destroyed by fire on 1952-01-14.
+#
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Antarctica/DumontDUrville 0 - zzz 1947
+ 10:00 - PMT 1952 Jan 14 # Port-Martin Time
+ 0 - zzz 1956 Nov
+ 10:00 - DDUT # Dumont-d'Urville Time
+# Reference:
+# <a href="http://en.wikipedia.org/wiki/Dumont_d'Urville_Station">
+# Dumont d'Urville Station (2005-12-05)
+# </a>
+
+# Germany - year-round base
+# Georg von Neumayer, -7039-00815
+
+# India - year-round base
+# Dakshin Gangotri, -7005+01200
+
+# Japan - year-round bases
+# Dome Fuji, -7719+03942
+# Syowa, -690022+0393524
+#
+# From Hideyuki Suzuki (1999-02-06):
+# In all Japanese stations, +0300 is used as the standard time.
+#
+# Syowa station, which is the first antarctic station of Japan,
+# was established on 1957-01-29. Since Syowa station is still the main
+# station of Japan, it's appropriate for the principal location.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Antarctica/Syowa 0 - zzz 1957 Jan 29
+ 3:00 - SYOT # Syowa Time
+# See:
+# <a href="http://www.nipr.ac.jp/english/ara01.html">
+# NIPR Antarctic Research Activities (1999-08-17)
+# </a>
+
+# S Korea - year-round base
+# King Sejong, King George Island, -6213-05847, since 1988
+
+# New Zealand - claims
+# Balleny Islands (never inhabited)
+# Scott Island (never inhabited)
+#
+# year-round base
+# Scott, Ross Island, since 1957-01, is like Antarctica/McMurdo.
+#
+# These rules for New Zealand are stolen from the `australasia' file.
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule NZAQ 1974 only - Nov 3 2:00s 1:00 D
+Rule NZAQ 1975 1988 - Oct lastSun 2:00s 1:00 D
+Rule NZAQ 1989 only - Oct 8 2:00s 1:00 D
+Rule NZAQ 1990 2006 - Oct Sun>=1 2:00s 1:00 D
+Rule NZAQ 1975 only - Feb 23 2:00s 0 S
+Rule NZAQ 1976 1989 - Mar Sun>=1 2:00s 0 S
+Rule NZAQ 1990 2007 - Mar Sun>=15 2:00s 0 S
+Rule NZAQ 2007 max - Sep lastSun 2:00s 1:00 D
+Rule NZAQ 2008 max - Apr Sun>=1 2:00s 0 S
+
+# Norway - territories
+# Bouvet (never inhabited)
+#
+# claims
+# Peter I Island (never inhabited)
+
+# Poland - year-round base
+# Arctowski, King George Island, -620945-0582745, since 1977
+
+# Russia - year-round bases
+# Bellingshausen, King George Island, -621159-0585337, since 1968-02-22
+# Mirny, Davis coast, -6633+09301, since 1956-02
+# Molodezhnaya, Alasheyev Bay, -6740+04551,
+# year-round from 1962-02 to 1999-07-01
+# Novolazarevskaya, Queen Maud Land, -7046+01150,
+# year-round from 1960/61 to 1992
+
+# Vostok, since 1957-12-16, temporarily closed 1994-02/1994-11
+# <a href="http://quest.arc.nasa.gov/antarctica/QA/computers/Directions,Time,ZIP">
+# From Craig Mundell (1994-12-15)</a>:
+# Vostok, which is one of the Russian stations, is set on the same
+# time as Moscow, Russia.
+#
+# From Lee Hotz (2001-03-08):
+# I queried the folks at Columbia who spent the summer at Vostok and this is
+# what they had to say about time there:
+# ``in the US Camp (East Camp) we have been on New Zealand (McMurdo)
+# time, which is 12 hours ahead of GMT. The Russian Station Vostok was
+# 6 hours behind that (although only 2 miles away, i.e. 6 hours ahead
+# of GMT). This is a time zone I think two hours east of Moscow. The
+# natural time zone is in between the two: 8 hours ahead of GMT.''
+#
+# From Paul Eggert (2001-05-04):
+# This seems to be hopelessly confusing, so I asked Lee Hotz about it
+# in person. He said that some Antartic locations set their local
+# time so that noon is the warmest part of the day, and that this
+# changes during the year and does not necessarily correspond to mean
+# solar noon. So the Vostok time might have been whatever the clocks
+# happened to be during their visit. So we still don't really know what time
+# it is at Vostok. But we'll guess UTC+6.
+#
+Zone Antarctica/Vostok 0 - zzz 1957 Dec 16
+ 6:00 - VOST # Vostok time
+
+# S Africa - year-round bases
+# Marion Island, -4653+03752
+# Sanae, -7141-00250
+
+# UK
+#
+# British Antarctic Territories (BAT) claims
+# South Orkney Islands
+# scientific station from 1903
+# whaling station at Signy I 1920/1926
+# South Shetland Islands
+#
+# year-round bases
+# Bird Island, South Georgia, -5400-03803, since 1983
+# Deception Island, -6259-06034, whaling station 1912/1931,
+# scientific station 1943/1967,
+# previously sealers and a scientific expedition wintered by accident,
+# and a garrison was deployed briefly
+# Halley, Coates Land, -7535-02604, since 1956-01-06
+# Halley is on a moving ice shelf and is periodically relocated
+# so that it is never more than 10km from its nominal location.
+# Rothera, Adelaide Island, -6734-6808, since 1976-12-01
+#
+# From Paul Eggert (2002-10-22)
+# <http://webexhibits.org/daylightsaving/g.html> says Rothera is -03 all year.
+#
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Antarctica/Rothera 0 - zzz 1976 Dec 1
+ -3:00 - ROTT # Rothera time
+
+# Uruguay - year round base
+# Artigas, King George Island, -621104-0585107
+
+# USA - year-round bases
+#
+# Palmer, Anvers Island, since 1965 (moved 2 miles in 1968)
+#
+# From Ethan Dicks (1996-10-06):
+# It keeps the same time as Punta Arenas, Chile, because, just like us
+# and the South Pole, that's the other end of their supply line....
+# I verified with someone who was there that since 1980,
+# Palmer has followed Chile. Prior to that, before the Falklands War,
+# Palmer used to be supplied from Argentina.
+#
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Antarctica/Palmer 0 - zzz 1965
+ -4:00 ArgAQ AR%sT 1969 Oct 5
+ -3:00 ArgAQ AR%sT 1982 May
+ -4:00 ChileAQ CL%sT
+#
+#
+# McMurdo, Ross Island, since 1955-12
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Antarctica/McMurdo 0 - zzz 1956
+ 12:00 NZAQ NZ%sT
+#
+# Amundsen-Scott, South Pole, continuously occupied since 1956-11-20
+#
+# From Paul Eggert (1996-09-03):
+# Normally it wouldn't have a separate entry, since it's like the
+# larger Antarctica/McMurdo since 1970, but it's too famous to omit.
+#
+# From Chris Carrier (1996-06-27):
+# Siple, the first commander of the South Pole station,
+# stated that he would have liked to have kept GMT at the station,
+# but that he found it more convenient to keep GMT+12
+# as supplies for the station were coming from McMurdo Sound,
+# which was on GMT+12 because New Zealand was on GMT+12 all year
+# at that time (1957). (Source: Siple's book 90 degrees SOUTH.)
+#
+# From Susan Smith
+# http://www.cybertours.com/whs/pole10.html
+# (1995-11-13 16:24:56 +1300, no longer available):
+# We use the same time as McMurdo does.
+# And they use the same time as Christchurch, NZ does....
+# One last quirk about South Pole time.
+# All the electric clocks are usually wrong.
+# Something about the generators running at 60.1hertz or something
+# makes all of the clocks run fast. So every couple of days,
+# we have to go around and set them back 5 minutes or so.
+# Maybe if we let them run fast all of the time, we'd get to leave here sooner!!
+#
+Link Antarctica/McMurdo Antarctica/South_Pole
diff --git a/tools/zoneinfo/tzdata2008h/asia b/tools/zoneinfo/tzdata2008h/asia
new file mode 100644
index 0000000..eb9f411
--- /dev/null
+++ b/tools/zoneinfo/tzdata2008h/asia
@@ -0,0 +1,2043 @@
+# @(#)asia 8.24
+# <pre>
+
+# This data is by no means authoritative; if you think you know better,
+# go ahead and edit the file (and please send any changes to
+# tz@elsie.nci.nih.gov for general use in the future).
+
+# From Paul Eggert (2006-03-22):
+#
+# A good source for time zone historical data outside the U.S. is
+# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
+# San Diego: ACS Publications, Inc. (2003).
+#
+# Gwillim Law writes that a good source
+# for recent time zone data is the International Air Transport
+# Association's Standard Schedules Information Manual (IATA SSIM),
+# published semiannually. Law sent in several helpful summaries
+# of the IATA's data after 1990.
+#
+# Except where otherwise noted, Shanks & Pottenger is the source for
+# entries through 1990, and IATA SSIM is the source for entries afterwards.
+#
+# Another source occasionally used is Edward W. Whitman, World Time Differences,
+# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which
+# I found in the UCLA library.
+#
+# A reliable and entertaining source about time zones is
+# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
+#
+# I invented the abbreviations marked `*' in the following table;
+# the rest are from earlier versions of this file, or from other sources.
+# Corrections are welcome!
+# std dst
+# LMT Local Mean Time
+# 2:00 EET EEST Eastern European Time
+# 2:00 IST IDT Israel
+# 3:00 AST ADT Arabia*
+# 3:30 IRST IRDT Iran
+# 4:00 GST Gulf*
+# 5:30 IST India
+# 7:00 ICT Indochina*
+# 7:00 WIT west Indonesia
+# 8:00 CIT central Indonesia
+# 8:00 CST China
+# 9:00 CJT Central Japanese Time (1896/1937)*
+# 9:00 EIT east Indonesia
+# 9:00 JST JDT Japan
+# 9:00 KST KDT Korea
+# 9:30 CST (Australian) Central Standard Time
+#
+# See the `europe' file for Russia and Turkey in Asia.
+
+# From Guy Harris:
+# Incorporates data for Singapore from Robert Elz' asia 1.1, as well as
+# additional information from Tom Yap, Sun Microsystems Intercontinental
+# Technical Support (including a page from the Official Airline Guide -
+# Worldwide Edition). The names for time zones are guesses.
+
+###############################################################################
+
+# These rules are stolen from the `europe' file.
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule EUAsia 1981 max - Mar lastSun 1:00u 1:00 S
+Rule EUAsia 1979 1995 - Sep lastSun 1:00u 0 -
+Rule EUAsia 1996 max - Oct lastSun 1:00u 0 -
+Rule E-EurAsia 1981 max - Mar lastSun 0:00 1:00 S
+Rule E-EurAsia 1979 1995 - Sep lastSun 0:00 0 -
+Rule E-EurAsia 1996 max - Oct lastSun 0:00 0 -
+Rule RussiaAsia 1981 1984 - Apr 1 0:00 1:00 S
+Rule RussiaAsia 1981 1983 - Oct 1 0:00 0 -
+Rule RussiaAsia 1984 1991 - Sep lastSun 2:00s 0 -
+Rule RussiaAsia 1985 1991 - Mar lastSun 2:00s 1:00 S
+Rule RussiaAsia 1992 only - Mar lastSat 23:00 1:00 S
+Rule RussiaAsia 1992 only - Sep lastSat 23:00 0 -
+Rule RussiaAsia 1993 max - Mar lastSun 2:00s 1:00 S
+Rule RussiaAsia 1993 1995 - Sep lastSun 2:00s 0 -
+Rule RussiaAsia 1996 max - Oct lastSun 2:00s 0 -
+
+# Afghanistan
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Kabul 4:36:48 - LMT 1890
+ 4:00 - AFT 1945
+ 4:30 - AFT
+
+# Armenia
+# From Paul Eggert (2006-03-22):
+# Shanks & Pottenger have Yerevan switching to 3:00 (with Russian DST)
+# in spring 1991, then to 4:00 with no DST in fall 1995, then
+# readopting Russian DST in 1997. Go with Shanks & Pottenger, even
+# when they disagree with others. Edgar Der-Danieliantz
+# reported (1996-05-04) that Yerevan probably wouldn't use DST
+# in 1996, though it did use DST in 1995. IATA SSIM (1991/1998) reports that
+# Armenia switched from 3:00 to 4:00 in 1998 and observed DST after 1991,
+# but started switching at 3:00s in 1998.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Yerevan 2:58:00 - LMT 1924 May 2
+ 3:00 - YERT 1957 Mar # Yerevan Time
+ 4:00 RussiaAsia YER%sT 1991 Mar 31 2:00s
+ 3:00 1:00 YERST 1991 Sep 23 # independence
+ 3:00 RussiaAsia AM%sT 1995 Sep 24 2:00s
+ 4:00 - AMT 1997
+ 4:00 RussiaAsia AM%sT
+
+# Azerbaijan
+# From Rustam Aliyev of the Azerbaijan Internet Forum (2005-10-23):
+# According to the resolution of Cabinet of Ministers, 1997
+# Resolution available at: http://aif.az/docs/daylight_res.pdf
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Azer 1997 max - Mar lastSun 4:00 1:00 S
+Rule Azer 1997 max - Oct lastSun 5:00 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Baku 3:19:24 - LMT 1924 May 2
+ 3:00 - BAKT 1957 Mar # Baku Time
+ 4:00 RussiaAsia BAK%sT 1991 Mar 31 2:00s
+ 3:00 1:00 BAKST 1991 Aug 30 # independence
+ 3:00 RussiaAsia AZ%sT 1992 Sep lastSat 23:00
+ 4:00 - AZT 1996 # Azerbaijan time
+ 4:00 EUAsia AZ%sT 1997
+ 4:00 Azer AZ%sT
+
+# Bahrain
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Bahrain 3:22:20 - LMT 1920 # Al Manamah
+ 4:00 - GST 1972 Jun
+ 3:00 - AST
+
+# Bangladesh
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Dhaka 6:01:40 - LMT 1890
+ 5:53:20 - HMT 1941 Oct # Howrah Mean Time?
+ 6:30 - BURT 1942 May 15 # Burma Time
+ 5:30 - IST 1942 Sep
+ 6:30 - BURT 1951 Sep 30
+ 6:00 - DACT 1971 Mar 26 # Dacca Time
+ 6:00 - BDT # Bangladesh Time
+
+# Bhutan
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Thimphu 5:58:36 - LMT 1947 Aug 15 # or Thimbu
+ 5:30 - IST 1987 Oct
+ 6:00 - BTT # Bhutan Time
+
+# British Indian Ocean Territory
+# Whitman and the 1995 CIA time zone map say 5:00, but the
+# 1997 and later maps say 6:00. Assume the switch occurred in 1996.
+# We have no information as to when standard time was introduced;
+# assume it occurred in 1907, the same year as Mauritius (which
+# then contained the Chagos Archipelago).
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Indian/Chagos 4:49:40 - LMT 1907
+ 5:00 - IOT 1996 # BIOT Time
+ 6:00 - IOT
+
+# Brunei
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Brunei 7:39:40 - LMT 1926 Mar # Bandar Seri Begawan
+ 7:30 - BNT 1933
+ 8:00 - BNT
+
+# Burma / Myanmar
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Rangoon 6:24:40 - LMT 1880 # or Yangon
+ 6:24:36 - RMT 1920 # Rangoon Mean Time?
+ 6:30 - BURT 1942 May # Burma Time
+ 9:00 - JST 1945 May 3
+ 6:30 - MMT # Myanmar Time
+
+# Cambodia
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Phnom_Penh 6:59:40 - LMT 1906 Jun 9
+ 7:06:20 - SMT 1911 Mar 11 0:01 # Saigon MT?
+ 7:00 - ICT 1912 May
+ 8:00 - ICT 1931 May
+ 7:00 - ICT
+
+# China
+
+# From Guy Harris:
+# People's Republic of China. Yes, they really have only one time zone.
+
+# From Bob Devine (1988-01-28):
+# No they don't. See TIME mag, 1986-02-17 p.52. Even though
+# China is across 4 physical time zones, before Feb 1, 1986 only the
+# Peking (Bejing) time zone was recognized. Since that date, China
+# has two of 'em -- Peking's and Urumqi (named after the capital of
+# the Xinjiang Uyghur Autonomous Region). I don't know about DST for it.
+#
+# . . .I just deleted the DST table and this editor makes it too
+# painful to suck in another copy.. So, here is what I have for
+# DST start/end dates for Peking's time zone (info from AP):
+#
+# 1986 May 4 - Sept 14
+# 1987 mid-April - ??
+
+# From U. S. Naval Observatory (1989-01-19):
+# CHINA 8 H AHEAD OF UTC ALL OF CHINA, INCL TAIWAN
+# CHINA 9 H AHEAD OF UTC APR 17 - SEP 10
+
+# From Paul Eggert (2006-03-22):
+# Shanks & Pottenger write that China (except for Hong Kong and Macau)
+# has had a single time zone since 1980 May 1, observing summer DST
+# from 1986 through 1991; this contradicts Devine's
+# note about Time magazine, though apparently _something_ happened in 1986.
+# Go with Shanks & Pottenger for now. I made up names for the other
+# pre-1980 time zones.
+
+# From Shanks & Pottenger:
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Shang 1940 only - Jun 3 0:00 1:00 D
+Rule Shang 1940 1941 - Oct 1 0:00 0 S
+Rule Shang 1941 only - Mar 16 0:00 1:00 D
+Rule PRC 1986 only - May 4 0:00 1:00 D
+Rule PRC 1986 1991 - Sep Sun>=11 0:00 0 S
+Rule PRC 1987 1991 - Apr Sun>=10 0:00 1:00 D
+
+# From Anthony Fok (2001-12-20):
+# BTW, I did some research on-line and found some info regarding these five
+# historic timezones from some Taiwan websites. And yes, there are official
+# Chinese names for these locales (before 1949).
+#
+# From Jesper Norgaard Welen (2006-07-14):
+# I have investigated the timezones around 1970 on the
+# http://www.astro.com/atlas site [with provinces and county
+# boundaries summarized below].... A few other exceptions were two
+# counties on the Sichuan side of the Xizang-Sichuan border,
+# counties Dege and Baiyu which lies on the Sichuan side and are
+# therefore supposed to be GMT+7, Xizang region being GMT+6, but Dege
+# county is GMT+8 according to astro.com while Baiyu county is GMT+6
+# (could be true), for the moment I am assuming that those two
+# counties are mistakes in the astro.com data.
+
+# From Paul Eggert (2008-02-11):
+# I just now checked Google News for western news sources that talk
+# about China's single time zone, and couldn't find anything before 1986
+# talking about China being in one time zone. (That article was: Jim
+# Mann, "A clumsy embrace for another western custom: China on daylight
+# time--sort of", Los Angeles Times, 1986-05-05. By the way, this
+# article confirms the tz database's data claiming that China began
+# observing daylight saving time in 1986.
+#
+# From Thomas S. Mullaney (2008-02-11):
+# I think you're combining two subjects that need to treated
+# separately: daylight savings (which, you're correct, wasn't
+# implemented until the 1980s) and the unified time zone centered near
+# Beijing (which was implemented in 1949). Briefly, there was also a
+# "Lhasa Time" in Tibet and "Urumqi Time" in Xinjiang. The first was
+# ceased, and the second eventually recognized (again, in the 1980s).
+#
+# From Paul Eggert (2008-06-30):
+# There seems to be a good chance China switched to a single time zone in 1949
+# rather than in 1980 as Shanks & Pottenger have it, but we don't have a
+# reliable documentary source saying so yet, so for now we still go with
+# Shanks & Pottenger.
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Changbai Time ("Long-white Time", Long-white = Heilongjiang area)
+# Heilongjiang (except Mohe county), Jilin
+Zone Asia/Harbin 8:26:44 - LMT 1928 # or Haerbin
+ 8:30 - CHAT 1932 Mar # Changbai Time
+ 8:00 - CST 1940
+ 9:00 - CHAT 1966 May
+ 8:30 - CHAT 1980 May
+ 8:00 PRC C%sT
+# Zhongyuan Time ("Central plain Time")
+# most of China
+Zone Asia/Shanghai 8:05:52 - LMT 1928
+ 8:00 Shang C%sT 1949
+ 8:00 PRC C%sT
+# Long-shu Time (probably due to Long and Shu being two names of that area)
+# Guangxi, Guizhou, Hainan, Ningxia, Sichuan, Shaanxi, and Yunnan;
+# most of Gansu; west Inner Mongolia; west Qinghai; and the Guangdong
+# counties Deqing, Enping, Kaiping, Luoding, Taishan, Xinxing,
+# Yangchun, Yangjiang, Yu'nan, and Yunfu.
+Zone Asia/Chongqing 7:06:20 - LMT 1928 # or Chungking
+ 7:00 - LONT 1980 May # Long-shu Time
+ 8:00 PRC C%sT
+# Xin-zang Time ("Xinjiang-Tibet Time")
+# The Gansu counties Aksay, Anxi, Dunhuang, Subei; west Qinghai;
+# the Guangdong counties Xuwen, Haikang, Suixi, Lianjiang,
+# Zhanjiang, Wuchuan, Huazhou, Gaozhou, Maoming, Dianbai, and Xinyi;
+# east Tibet, including Lhasa, Chamdo, Shigaise, Jimsar, Shawan and Hutubi;
+# east Xinjiang, including Urumqi, Turpan, Karamay, Korla, Minfeng, Jinghe,
+# Wusu, Qiemo, Xinyan, Wulanwusu, Jinghe, Yumin, Tacheng, Tuoli, Emin,
+# Shihezi, Changji, Yanqi, Heshuo, Tuokexun, Tulufan, Shanshan, Hami,
+# Fukang, Kuitun, Kumukuli, Miquan, Qitai, and Turfan.
+Zone Asia/Urumqi 5:50:20 - LMT 1928 # or Urumchi
+ 6:00 - URUT 1980 May # Urumqi Time
+ 8:00 PRC C%sT
+# Kunlun Time
+# West Tibet, including Pulan, Aheqi, Shufu, Shule;
+# West Xinjiang, including Aksu, Atushi, Yining, Hetian, Cele, Luopu, Nileke,
+# Zhaosu, Tekesi, Gongliu, Chabuchaer, Huocheng, Bole, Pishan, Suiding,
+# and Yarkand.
+Zone Asia/Kashgar 5:03:56 - LMT 1928 # or Kashi or Kaxgar
+ 5:30 - KAST 1940 # Kashgar Time
+ 5:00 - KAST 1980 May
+ 8:00 PRC C%sT
+
+# Hong Kong (Xianggang)
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule HK 1946 only - Apr 20 3:30 1:00 S
+Rule HK 1946 only - Dec 1 3:30 0 -
+Rule HK 1947 only - Apr 13 3:30 1:00 S
+Rule HK 1947 only - Dec 30 3:30 0 -
+Rule HK 1948 only - May 2 3:30 1:00 S
+Rule HK 1948 1952 - Oct lastSun 3:30 0 -
+Rule HK 1949 1953 - Apr Sun>=1 3:30 1:00 S
+Rule HK 1953 only - Nov 1 3:30 0 -
+Rule HK 1954 1964 - Mar Sun>=18 3:30 1:00 S
+Rule HK 1954 only - Oct 31 3:30 0 -
+Rule HK 1955 1964 - Nov Sun>=1 3:30 0 -
+Rule HK 1965 1977 - Apr Sun>=16 3:30 1:00 S
+Rule HK 1965 1977 - Oct Sun>=16 3:30 0 -
+Rule HK 1979 1980 - May Sun>=8 3:30 1:00 S
+Rule HK 1979 1980 - Oct Sun>=16 3:30 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Hong_Kong 7:36:36 - LMT 1904 Oct 30
+ 8:00 HK HK%sT
+
+
+###############################################################################
+
+# Taiwan
+
+# Shanks & Pottenger write that Taiwan observed DST during 1945, when it
+# was still controlled by Japan. This is hard to believe, but we don't
+# have any other information.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Taiwan 1945 1951 - May 1 0:00 1:00 D
+Rule Taiwan 1945 1951 - Oct 1 0:00 0 S
+Rule Taiwan 1952 only - Mar 1 0:00 1:00 D
+Rule Taiwan 1952 1954 - Nov 1 0:00 0 S
+Rule Taiwan 1953 1959 - Apr 1 0:00 1:00 D
+Rule Taiwan 1955 1961 - Oct 1 0:00 0 S
+Rule Taiwan 1960 1961 - Jun 1 0:00 1:00 D
+Rule Taiwan 1974 1975 - Apr 1 0:00 1:00 D
+Rule Taiwan 1974 1975 - Oct 1 0:00 0 S
+Rule Taiwan 1980 only - Jun 30 0:00 1:00 D
+Rule Taiwan 1980 only - Sep 30 0:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Taipei 8:06:00 - LMT 1896 # or Taibei or T'ai-pei
+ 8:00 Taiwan C%sT
+
+# Macau (Macao, Aomen)
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Macau 1961 1962 - Mar Sun>=16 3:30 1:00 S
+Rule Macau 1961 1964 - Nov Sun>=1 3:30 0 -
+Rule Macau 1963 only - Mar Sun>=16 0:00 1:00 S
+Rule Macau 1964 only - Mar Sun>=16 3:30 1:00 S
+Rule Macau 1965 only - Mar Sun>=16 0:00 1:00 S
+Rule Macau 1965 only - Oct 31 0:00 0 -
+Rule Macau 1966 1971 - Apr Sun>=16 3:30 1:00 S
+Rule Macau 1966 1971 - Oct Sun>=16 3:30 0 -
+Rule Macau 1972 1974 - Apr Sun>=15 0:00 1:00 S
+Rule Macau 1972 1973 - Oct Sun>=15 0:00 0 -
+Rule Macau 1974 1977 - Oct Sun>=15 3:30 0 -
+Rule Macau 1975 1977 - Apr Sun>=15 3:30 1:00 S
+Rule Macau 1978 1980 - Apr Sun>=15 0:00 1:00 S
+Rule Macau 1978 1980 - Oct Sun>=15 0:00 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Macau 7:34:20 - LMT 1912
+ 8:00 Macau MO%sT 1999 Dec 20 # return to China
+ 8:00 PRC C%sT
+
+
+###############################################################################
+
+# Cyprus
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Cyprus 1975 only - Apr 13 0:00 1:00 S
+Rule Cyprus 1975 only - Oct 12 0:00 0 -
+Rule Cyprus 1976 only - May 15 0:00 1:00 S
+Rule Cyprus 1976 only - Oct 11 0:00 0 -
+Rule Cyprus 1977 1980 - Apr Sun>=1 0:00 1:00 S
+Rule Cyprus 1977 only - Sep 25 0:00 0 -
+Rule Cyprus 1978 only - Oct 2 0:00 0 -
+Rule Cyprus 1979 1997 - Sep lastSun 0:00 0 -
+Rule Cyprus 1981 1998 - Mar lastSun 0:00 1:00 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Nicosia 2:13:28 - LMT 1921 Nov 14
+ 2:00 Cyprus EE%sT 1998 Sep
+ 2:00 EUAsia EE%sT
+# IATA SSIM (1998-09) has Cyprus using EU rules for the first time.
+
+# Classically, Cyprus belongs to Asia; e.g. see Herodotus, Histories, I.72.
+# However, for various reasons many users expect to find it under Europe.
+Link Asia/Nicosia Europe/Nicosia
+
+# Georgia
+# From Paul Eggert (1994-11-19):
+# Today's _Economist_ (p 60) reports that Georgia moved its clocks forward
+# an hour recently, due to a law proposed by Zurab Murvanidze,
+# an MP who went on a hunger strike for 11 days to force discussion about it!
+# We have no details, but we'll guess they didn't move the clocks back in fall.
+#
+# From Mathew Englander, quoting AP (1996-10-23 13:05-04):
+# Instead of putting back clocks at the end of October, Georgia
+# will stay on daylight savings time this winter to save energy,
+# President Eduard Shevardnadze decreed Wednesday.
+#
+# From the BBC via Joseph S. Myers (2004-06-27):
+#
+# Georgia moved closer to Western Europe on Sunday... The former Soviet
+# republic has changed its time zone back to that of Moscow. As a result it
+# is now just four hours ahead of Greenwich Mean Time, rather than five hours
+# ahead. The switch was decreed by the pro-Western president of Georgia,
+# Mikhail Saakashvili, who said the change was partly prompted by the process
+# of integration into Europe.
+
+# From Teimuraz Abashidze (2005-11-07):
+# Government of Georgia ... decided to NOT CHANGE daylight savings time on
+# [Oct.] 30, as it was done before during last more than 10 years.
+# Currently, we are in fact GMT +4:00, as before 30 October it was GMT
+# +3:00.... The problem is, there is NO FORMAL LAW or governmental document
+# about it. As far as I can find, I was told, that there is no document,
+# because we just DIDN'T ISSUE document about switching to winter time....
+# I don't know what can be done, especially knowing that some years ago our
+# DST rules where changed THREE TIMES during one month.
+
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Tbilisi 2:59:16 - LMT 1880
+ 2:59:16 - TBMT 1924 May 2 # Tbilisi Mean Time
+ 3:00 - TBIT 1957 Mar # Tbilisi Time
+ 4:00 RussiaAsia TBI%sT 1991 Mar 31 2:00s
+ 3:00 1:00 TBIST 1991 Apr 9 # independence
+ 3:00 RussiaAsia GE%sT 1992 # Georgia Time
+ 3:00 E-EurAsia GE%sT 1994 Sep lastSun
+ 4:00 E-EurAsia GE%sT 1996 Oct lastSun
+ 4:00 1:00 GEST 1997 Mar lastSun
+ 4:00 E-EurAsia GE%sT 2004 Jun 27
+ 3:00 RussiaAsia GE%sT 2005 Mar lastSun 2:00
+ 4:00 - GET
+
+# East Timor
+
+# See Indonesia for the 1945 transition.
+
+# From Joao Carrascalao, brother of the former governor of East Timor, in
+# <a href="http://etan.org/et99c/december/26-31/30ETMAY.htm">
+# East Timor may be late for its millennium
+# </a> (1999-12-26/31):
+# Portugal tried to change the time forward in 1974 because the sun
+# rises too early but the suggestion raised a lot of problems with the
+# Timorese and I still don't think it would work today because it
+# conflicts with their way of life.
+
+# From Paul Eggert (2000-12-04):
+# We don't have any record of the above attempt.
+# Most likely our records are incomplete, but we have no better data.
+
+# <a href="http://www.hri.org/news/world/undh/last/00-08-16.undh.html">
+# From Manoel de Almeida e Silva, Deputy Spokesman for the UN Secretary-General
+# (2000-08-16)</a>:
+# The Cabinet of the East Timor Transition Administration decided
+# today to advance East Timor's time by one hour. The time change,
+# which will be permanent, with no seasonal adjustment, will happen at
+# midnight on Saturday, September 16.
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Dili 8:22:20 - LMT 1912
+ 8:00 - TLT 1942 Feb 21 23:00 # E Timor Time
+ 9:00 - JST 1945 Sep 23
+ 9:00 - TLT 1976 May 3
+ 8:00 - CIT 2000 Sep 17 00:00
+ 9:00 - TLT
+
+# India
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Kolkata 5:53:28 - LMT 1880 # Kolkata
+ 5:53:20 - HMT 1941 Oct # Howrah Mean Time?
+ 6:30 - BURT 1942 May 15 # Burma Time
+ 5:30 - IST 1942 Sep
+ 5:30 1:00 IST 1945 Oct 15
+ 5:30 - IST
+# The following are like Asia/Kolkata:
+# Andaman Is
+# Lakshadweep (Laccadive, Minicoy and Amindivi Is)
+# Nicobar Is
+
+# Indonesia
+#
+# From Gwillim Law (2001-05-28), overriding Shanks & Pottenger:
+# <http://www.sumatera-inc.com/go_to_invest/about_indonesia.asp#standtime>
+# says that Indonesia's time zones changed on 1988-01-01. Looking at some
+# time zone maps, I think that must refer to Western Borneo (Kalimantan Barat
+# and Kalimantan Tengah) switching from UTC+8 to UTC+7.
+#
+# From Paul Eggert (2007-03-10):
+# Here is another correction to Shanks & Pottenger.
+# JohnTWB writes that Japanese forces did not surrender control in
+# Indonesia until 1945-09-01 00:00 at the earliest (in Jakarta) and
+# other formal surrender ceremonies were September 9, 11, and 13, plus
+# September 12 for the regional surrender to Mountbatten in Singapore.
+# These would be the earliest possible times for a change.
+# Regimes horaires pour le monde entier, by Henri Le Corre, (Editions
+# Traditionnelles, 1987, Paris) says that Java and Madura switched
+# from JST to UTC+07:30 on 1945-09-23, and gives 1944-09-01 for Jayapura
+# (Hollandia). For now, assume all Indonesian locations other than Jayapura
+# switched on 1945-09-23.
+#
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Jakarta 7:07:12 - LMT 1867 Aug 10
+# Shanks & Pottenger say the next transition was at 1924 Jan 1 0:13,
+# but this must be a typo.
+ 7:07:12 - JMT 1923 Dec 31 23:47:12 # Jakarta
+ 7:20 - JAVT 1932 Nov # Java Time
+ 7:30 - WIT 1942 Mar 23
+ 9:00 - JST 1945 Sep 23
+ 7:30 - WIT 1948 May
+ 8:00 - WIT 1950 May
+ 7:30 - WIT 1964
+ 7:00 - WIT
+Zone Asia/Pontianak 7:17:20 - LMT 1908 May
+ 7:17:20 - PMT 1932 Nov # Pontianak MT
+ 7:30 - WIT 1942 Jan 29
+ 9:00 - JST 1945 Sep 23
+ 7:30 - WIT 1948 May
+ 8:00 - WIT 1950 May
+ 7:30 - WIT 1964
+ 8:00 - CIT 1988 Jan 1
+ 7:00 - WIT
+Zone Asia/Makassar 7:57:36 - LMT 1920
+ 7:57:36 - MMT 1932 Nov # Macassar MT
+ 8:00 - CIT 1942 Feb 9
+ 9:00 - JST 1945 Sep 23
+ 8:00 - CIT
+Zone Asia/Jayapura 9:22:48 - LMT 1932 Nov
+ 9:00 - EIT 1944 Sep 1
+ 9:30 - CST 1964
+ 9:00 - EIT
+
+# Iran
+
+# From Roozbeh Pournader (2003-03-15):
+# This is an English translation of what I just found (originally in Persian).
+# The Gregorian dates in brackets are mine:
+#
+# Official Newspaper No. 13548-1370/6/25 [1991-09-16]
+# No. 16760/T233 H 1370/6/10 [1991-09-01]
+#
+# The Rule About Change of the Official Time of the Country
+#
+# The Board of Ministers, in the meeting dated 1370/5/23 [1991-08-14],
+# based on the suggestion number 2221/D dated 1370/4/22 [1991-07-13]
+# of the Country's Organization for Official and Employment Affairs,
+# and referring to the law for equating the working hours of workers
+# and officers in the whole country dated 1359/4/23 [1980-07-14], and
+# for synchronizing the official times of the country, agreed that:
+#
+# The official time of the country will should move forward one hour
+# at the 24[:00] hours of the first day of Farvardin and should return
+# to its previous state at the 24[:00] hours of the 30th day of
+# Shahrivar.
+#
+# First Deputy to the President - Hassan Habibi
+#
+# From personal experience, that agrees with what has been followed
+# for at least the last 5 years. Before that, for a few years, the
+# date used was the first Thursday night of Farvardin and the last
+# Thursday night of Shahrivar, but I can't give exact dates....
+# I have also changed the abbreviations to what is considered correct
+# here in Iran, IRST for regular time and IRDT for daylight saving time.
+#
+# From Roozbeh Pournader (2005-04-05):
+# The text of the Iranian law, in effect since 1925, clearly mentions
+# that the true solar year is the measure, and there is no arithmetic
+# leap year calculation involved. There has never been any serious
+# plan to change that law....
+#
+# From Paul Eggert (2006-03-22):
+# Go with Shanks & Pottenger before Sept. 1991, and with Pournader thereafter.
+# I used Ed Reingold's cal-persia in GNU Emacs 21.2 to check Persian dates,
+# stopping after 2037 when 32-bit time_t's overflow.
+# That cal-persia used Birashk's approximation, which disagrees with the solar
+# calendar predictions for the year 2025, so I corrected those dates by hand.
+#
+# From Oscar van Vlijmen (2005-03-30), writing about future
+# discrepancies between cal-persia and the Iranian calendar:
+# For 2091 solar-longitude-after yields 2091-03-20 08:40:07.7 UT for
+# the vernal equinox and that gets so close to 12:00 some local
+# Iranian time that the definition of the correct location needs to be
+# known exactly, amongst other factors. 2157 is even closer:
+# 2157-03-20 08:37:15.5 UT. But the Gregorian year 2025 should give
+# no interpretation problem whatsoever. By the way, another instant
+# in the near future where there will be a discrepancy between
+# arithmetical and astronomical Iranian calendars will be in 2058:
+# vernal equinox on 2058-03-20 09:03:05.9 UT. The Java version of
+# Reingold's/Dershowitz' calculator gives correctly the Gregorian date
+# 2058-03-21 for 1 Farvardin 1437 (astronomical).
+#
+# From Steffen Thorsen (2006-03-22):
+# Several of my users have reported that Iran will not observe DST anymore:
+# http://www.irna.ir/en/news/view/line-17/0603193812164948.htm
+#
+# From Reuters (2007-09-16), with a heads-up from Jesper Norgaard Welen:
+# ... the Guardian Council ... approved a law on Sunday to re-introduce
+# daylight saving time ...
+# http://uk.reuters.com/article/oilRpt/idUKBLA65048420070916
+#
+# From Roozbeh Pournader (2007-11-05):
+# This is quoted from Official Gazette of the Islamic Republic of
+# Iran, Volume 63, Number 18242, dated Tuesday 1386/6/24
+# [2007-10-16]. I am doing the best translation I can:...
+# The official time of the country will be moved forward for one hour
+# on the 24 hours of the first day of the month of Farvardin and will
+# be changed back to its previous state on the 24 hours of the
+# thirtieth day of Shahrivar.
+#
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Iran 1978 1980 - Mar 21 0:00 1:00 D
+Rule Iran 1978 only - Oct 21 0:00 0 S
+Rule Iran 1979 only - Sep 19 0:00 0 S
+Rule Iran 1980 only - Sep 23 0:00 0 S
+Rule Iran 1991 only - May 3 0:00 1:00 D
+Rule Iran 1992 1995 - Mar 22 0:00 1:00 D
+Rule Iran 1991 1995 - Sep 22 0:00 0 S
+Rule Iran 1996 only - Mar 21 0:00 1:00 D
+Rule Iran 1996 only - Sep 21 0:00 0 S
+Rule Iran 1997 1999 - Mar 22 0:00 1:00 D
+Rule Iran 1997 1999 - Sep 22 0:00 0 S
+Rule Iran 2000 only - Mar 21 0:00 1:00 D
+Rule Iran 2000 only - Sep 21 0:00 0 S
+Rule Iran 2001 2003 - Mar 22 0:00 1:00 D
+Rule Iran 2001 2003 - Sep 22 0:00 0 S
+Rule Iran 2004 only - Mar 21 0:00 1:00 D
+Rule Iran 2004 only - Sep 21 0:00 0 S
+Rule Iran 2005 only - Mar 22 0:00 1:00 D
+Rule Iran 2005 only - Sep 22 0:00 0 S
+Rule Iran 2008 only - Mar 21 0:00 1:00 D
+Rule Iran 2008 only - Sep 21 0:00 0 S
+Rule Iran 2009 2011 - Mar 22 0:00 1:00 D
+Rule Iran 2009 2011 - Sep 22 0:00 0 S
+Rule Iran 2012 only - Mar 21 0:00 1:00 D
+Rule Iran 2012 only - Sep 21 0:00 0 S
+Rule Iran 2013 2015 - Mar 22 0:00 1:00 D
+Rule Iran 2013 2015 - Sep 22 0:00 0 S
+Rule Iran 2016 only - Mar 21 0:00 1:00 D
+Rule Iran 2016 only - Sep 21 0:00 0 S
+Rule Iran 2017 2019 - Mar 22 0:00 1:00 D
+Rule Iran 2017 2019 - Sep 22 0:00 0 S
+Rule Iran 2020 only - Mar 21 0:00 1:00 D
+Rule Iran 2020 only - Sep 21 0:00 0 S
+Rule Iran 2021 2023 - Mar 22 0:00 1:00 D
+Rule Iran 2021 2023 - Sep 22 0:00 0 S
+Rule Iran 2024 only - Mar 21 0:00 1:00 D
+Rule Iran 2024 only - Sep 21 0:00 0 S
+Rule Iran 2025 2027 - Mar 22 0:00 1:00 D
+Rule Iran 2025 2027 - Sep 22 0:00 0 S
+Rule Iran 2028 2029 - Mar 21 0:00 1:00 D
+Rule Iran 2028 2029 - Sep 21 0:00 0 S
+Rule Iran 2030 2031 - Mar 22 0:00 1:00 D
+Rule Iran 2030 2031 - Sep 22 0:00 0 S
+Rule Iran 2032 2033 - Mar 21 0:00 1:00 D
+Rule Iran 2032 2033 - Sep 21 0:00 0 S
+Rule Iran 2034 2035 - Mar 22 0:00 1:00 D
+Rule Iran 2034 2035 - Sep 22 0:00 0 S
+Rule Iran 2036 2037 - Mar 21 0:00 1:00 D
+Rule Iran 2036 2037 - Sep 21 0:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Tehran 3:25:44 - LMT 1916
+ 3:25:44 - TMT 1946 # Tehran Mean Time
+ 3:30 - IRST 1977 Nov
+ 4:00 Iran IR%sT 1979
+ 3:30 Iran IR%sT
+
+
+# Iraq
+#
+# From Jonathan Lennox (2000-06-12):
+# An article in this week's Economist ("Inside the Saddam-free zone", p. 50 in
+# the U.S. edition) on the Iraqi Kurds contains a paragraph:
+# "The three northern provinces ... switched their clocks this spring and
+# are an hour ahead of Baghdad."
+#
+# But Rives McDow (2000-06-18) quotes a contact in Iraqi-Kurdistan as follows:
+# In the past, some Kurdish nationalists, as a protest to the Iraqi
+# Government, did not adhere to daylight saving time. They referred
+# to daylight saving as Saddam time. But, as of today, the time zone
+# in Iraqi-Kurdistan is on standard time with Baghdad, Iraq.
+#
+# So we'll ignore the Economist's claim.
+
+# From Steffen Thorsen (2008-03-10):
+# The cabinet in Iraq abolished DST last week, according to the following
+# news sources (in Arabic):
+# <a href="http://www.aljeeran.net/wesima_articles/news-20080305-98602.html">
+# http://www.aljeeran.net/wesima_articles/news-20080305-98602.html
+# </a>
+# <a href="http://www.aswataliraq.info/look/article.tpl?id=2047&IdLanguage=17&IdPublication=4&NrArticle=71743&NrIssue=1&NrSection=10">
+# http://www.aswataliraq.info/look/article.tpl?id=2047&IdLanguage=17&IdPublication=4&NrArticle=71743&NrIssue=1&NrSection=10
+# </a>
+#
+# We have published a short article in English about the change:
+# <a href="http://www.timeanddate.com/news/time/iraq-dumps-daylight-saving.html">
+# http://www.timeanddate.com/news/time/iraq-dumps-daylight-saving.html
+# </a>
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Iraq 1982 only - May 1 0:00 1:00 D
+Rule Iraq 1982 1984 - Oct 1 0:00 0 S
+Rule Iraq 1983 only - Mar 31 0:00 1:00 D
+Rule Iraq 1984 1985 - Apr 1 0:00 1:00 D
+Rule Iraq 1985 1990 - Sep lastSun 1:00s 0 S
+Rule Iraq 1986 1990 - Mar lastSun 1:00s 1:00 D
+# IATA SSIM (1991/1996) says Apr 1 12:01am UTC; guess the `:01' is a typo.
+# Shanks & Pottenger say Iraq did not observe DST 1992/1997; ignore this.
+#
+Rule Iraq 1991 2007 - Apr 1 3:00s 1:00 D
+Rule Iraq 1991 2007 - Oct 1 3:00s 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Baghdad 2:57:40 - LMT 1890
+ 2:57:36 - BMT 1918 # Baghdad Mean Time?
+ 3:00 - AST 1982 May
+ 3:00 Iraq A%sT
+
+
+###############################################################################
+
+# Israel
+
+# From Ephraim Silverberg (2001-01-11):
+#
+# I coined "IST/IDT" circa 1988. Until then there were three
+# different abbreviations in use:
+#
+# JST Jerusalem Standard Time [Danny Braniss, Hebrew University]
+# IZT Israel Zonal (sic) Time [Prof. Haim Papo, Technion]
+# EEST Eastern Europe Standard Time [used by almost everyone else]
+#
+# Since timezones should be called by country and not capital cities,
+# I ruled out JST. As Israel is in Asia Minor and not Eastern Europe,
+# EEST was equally unacceptable. Since "zonal" was not compatible with
+# any other timezone abbreviation, I felt that 'IST' was the way to go
+# and, indeed, it has received almost universal acceptance in timezone
+# settings in Israeli computers.
+#
+# In any case, I am happy to share timezone abbreviations with India,
+# high on my favorite-country list (and not only because my wife's
+# family is from India).
+
+# From Shanks & Pottenger:
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Zion 1940 only - Jun 1 0:00 1:00 D
+Rule Zion 1942 1944 - Nov 1 0:00 0 S
+Rule Zion 1943 only - Apr 1 2:00 1:00 D
+Rule Zion 1944 only - Apr 1 0:00 1:00 D
+Rule Zion 1945 only - Apr 16 0:00 1:00 D
+Rule Zion 1945 only - Nov 1 2:00 0 S
+Rule Zion 1946 only - Apr 16 2:00 1:00 D
+Rule Zion 1946 only - Nov 1 0:00 0 S
+Rule Zion 1948 only - May 23 0:00 2:00 DD
+Rule Zion 1948 only - Sep 1 0:00 1:00 D
+Rule Zion 1948 1949 - Nov 1 2:00 0 S
+Rule Zion 1949 only - May 1 0:00 1:00 D
+Rule Zion 1950 only - Apr 16 0:00 1:00 D
+Rule Zion 1950 only - Sep 15 3:00 0 S
+Rule Zion 1951 only - Apr 1 0:00 1:00 D
+Rule Zion 1951 only - Nov 11 3:00 0 S
+Rule Zion 1952 only - Apr 20 2:00 1:00 D
+Rule Zion 1952 only - Oct 19 3:00 0 S
+Rule Zion 1953 only - Apr 12 2:00 1:00 D
+Rule Zion 1953 only - Sep 13 3:00 0 S
+Rule Zion 1954 only - Jun 13 0:00 1:00 D
+Rule Zion 1954 only - Sep 12 0:00 0 S
+Rule Zion 1955 only - Jun 11 2:00 1:00 D
+Rule Zion 1955 only - Sep 11 0:00 0 S
+Rule Zion 1956 only - Jun 3 0:00 1:00 D
+Rule Zion 1956 only - Sep 30 3:00 0 S
+Rule Zion 1957 only - Apr 29 2:00 1:00 D
+Rule Zion 1957 only - Sep 22 0:00 0 S
+Rule Zion 1974 only - Jul 7 0:00 1:00 D
+Rule Zion 1974 only - Oct 13 0:00 0 S
+Rule Zion 1975 only - Apr 20 0:00 1:00 D
+Rule Zion 1975 only - Aug 31 0:00 0 S
+Rule Zion 1985 only - Apr 14 0:00 1:00 D
+Rule Zion 1985 only - Sep 15 0:00 0 S
+Rule Zion 1986 only - May 18 0:00 1:00 D
+Rule Zion 1986 only - Sep 7 0:00 0 S
+Rule Zion 1987 only - Apr 15 0:00 1:00 D
+Rule Zion 1987 only - Sep 13 0:00 0 S
+Rule Zion 1988 only - Apr 9 0:00 1:00 D
+Rule Zion 1988 only - Sep 3 0:00 0 S
+
+# From Ephraim Silverberg
+# (1997-03-04, 1998-03-16, 1998-12-28, 2000-01-17, 2000-07-25, 2004-12-22,
+# and 2005-02-17):
+
+# According to the Office of the Secretary General of the Ministry of
+# Interior, there is NO set rule for Daylight-Savings/Standard time changes.
+# One thing is entrenched in law, however: that there must be at least 150
+# days of daylight savings time annually. From 1993-1998, the change to
+# daylight savings time was on a Friday morning from midnight IST to
+# 1 a.m IDT; up until 1998, the change back to standard time was on a
+# Saturday night from midnight daylight savings time to 11 p.m. standard
+# time. 1996 is an exception to this rule where the change back to standard
+# time took place on Sunday night instead of Saturday night to avoid
+# conflicts with the Jewish New Year. In 1999, the change to
+# daylight savings time was still on a Friday morning but from
+# 2 a.m. IST to 3 a.m. IDT; furthermore, the change back to standard time
+# was also on a Friday morning from 2 a.m. IDT to 1 a.m. IST for
+# 1999 only. In the year 2000, the change to daylight savings time was
+# similar to 1999, but although the change back will be on a Friday, it
+# will take place from 1 a.m. IDT to midnight IST. Starting in 2001, all
+# changes to/from will take place at 1 a.m. old time, but now there is no
+# rule as to what day of the week it will take place in as the start date
+# (except in 2003) is the night after the Passover Seder (i.e. the eve
+# of the 16th of Nisan in the lunar Hebrew calendar) and the end date
+# (except in 2002) is three nights before Yom Kippur [Day of Atonement]
+# (the eve of the 7th of Tishrei in the lunar Hebrew calendar).
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Zion 1989 only - Apr 30 0:00 1:00 D
+Rule Zion 1989 only - Sep 3 0:00 0 S
+Rule Zion 1990 only - Mar 25 0:00 1:00 D
+Rule Zion 1990 only - Aug 26 0:00 0 S
+Rule Zion 1991 only - Mar 24 0:00 1:00 D
+Rule Zion 1991 only - Sep 1 0:00 0 S
+Rule Zion 1992 only - Mar 29 0:00 1:00 D
+Rule Zion 1992 only - Sep 6 0:00 0 S
+Rule Zion 1993 only - Apr 2 0:00 1:00 D
+Rule Zion 1993 only - Sep 5 0:00 0 S
+
+# The dates for 1994-1995 were obtained from Office of the Spokeswoman for the
+# Ministry of Interior, Jerusalem, Israel. The spokeswoman can be reached by
+# calling the office directly at 972-2-6701447 or 972-2-6701448.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Zion 1994 only - Apr 1 0:00 1:00 D
+Rule Zion 1994 only - Aug 28 0:00 0 S
+Rule Zion 1995 only - Mar 31 0:00 1:00 D
+Rule Zion 1995 only - Sep 3 0:00 0 S
+
+# The dates for 1996 were determined by the Minister of Interior of the
+# time, Haim Ramon. The official announcement regarding 1996-1998
+# (with the dates for 1997-1998 no longer being relevant) can be viewed at:
+#
+# ftp://ftp.cs.huji.ac.il/pub/tz/announcements/1996-1998.ramon.ps.gz
+#
+# The dates for 1997-1998 were altered by his successor, Rabbi Eli Suissa.
+#
+# The official announcements for the years 1997-1999 can be viewed at:
+#
+# ftp://ftp.cs.huji.ac.il/pub/tz/announcements/YYYY.ps.gz
+#
+# where YYYY is the relevant year.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Zion 1996 only - Mar 15 0:00 1:00 D
+Rule Zion 1996 only - Sep 16 0:00 0 S
+Rule Zion 1997 only - Mar 21 0:00 1:00 D
+Rule Zion 1997 only - Sep 14 0:00 0 S
+Rule Zion 1998 only - Mar 20 0:00 1:00 D
+Rule Zion 1998 only - Sep 6 0:00 0 S
+Rule Zion 1999 only - Apr 2 2:00 1:00 D
+Rule Zion 1999 only - Sep 3 2:00 0 S
+
+# The Knesset Interior Committee has changed the dates for 2000 for
+# the third time in just over a year and have set new dates for the
+# years 2001-2004 as well.
+#
+# The official announcement for the start date of 2000 can be viewed at:
+#
+# ftp://ftp.cs.huji.ac.il/pub/tz/announcements/2000-start.ps.gz
+#
+# The official announcement for the end date of 2000 and the dates
+# for the years 2001-2004 can be viewed at:
+#
+# ftp://ftp.cs.huji.ac.il/pub/tz/announcements/2000-2004.ps.gz
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Zion 2000 only - Apr 14 2:00 1:00 D
+Rule Zion 2000 only - Oct 6 1:00 0 S
+Rule Zion 2001 only - Apr 9 1:00 1:00 D
+Rule Zion 2001 only - Sep 24 1:00 0 S
+Rule Zion 2002 only - Mar 29 1:00 1:00 D
+Rule Zion 2002 only - Oct 7 1:00 0 S
+Rule Zion 2003 only - Mar 28 1:00 1:00 D
+Rule Zion 2003 only - Oct 3 1:00 0 S
+Rule Zion 2004 only - Apr 7 1:00 1:00 D
+Rule Zion 2004 only - Sep 22 1:00 0 S
+
+# The proposed law agreed upon by the Knesset Interior Committee on
+# 2005-02-14 is that, for 2005 and beyond, DST starts at 02:00 the
+# last Friday before April 2nd (i.e. the last Friday in March or April
+# 1st itself if it falls on a Friday) and ends at 02:00 on the Saturday
+# night _before_ the fast of Yom Kippur.
+#
+# Those who can read Hebrew can view the announcement at:
+#
+# ftp://ftp.cs.huji.ac.il/pub/tz/announcements/2005+beyond.ps
+
+# From Paul Eggert (2005-02-22):
+# I used Ephraim Silverberg's dst-israel.el program
+# <ftp://ftp.cs.huji.ac.il/pub/tz/software/dst-israel.el> (2005-02-20)
+# along with Ed Reingold's cal-hebrew in GNU Emacs 21.4,
+# to generate the transitions in this list.
+# (I replaced "lastFri" with "Fri>=26" by hand.)
+# The spring transitions below all correspond to the following Rule:
+#
+# Rule Zion 2005 max - Mar Fri>=26 2:00 1:00 D
+#
+# but older zic implementations (e.g., Solaris 8) do not support
+# "Fri>=26" to mean April 1 in years like 2005, so for now we list the
+# springtime transitions explicitly.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Zion 2005 only - Apr 1 2:00 1:00 D
+Rule Zion 2005 only - Oct 9 2:00 0 S
+Rule Zion 2006 2010 - Mar Fri>=26 2:00 1:00 D
+Rule Zion 2006 only - Oct 1 2:00 0 S
+Rule Zion 2007 only - Sep 16 2:00 0 S
+Rule Zion 2008 only - Oct 5 2:00 0 S
+Rule Zion 2009 only - Sep 27 2:00 0 S
+Rule Zion 2010 only - Sep 12 2:00 0 S
+Rule Zion 2011 only - Apr 1 2:00 1:00 D
+Rule Zion 2011 only - Oct 2 2:00 0 S
+Rule Zion 2012 2015 - Mar Fri>=26 2:00 1:00 D
+Rule Zion 2012 only - Sep 23 2:00 0 S
+Rule Zion 2013 only - Sep 8 2:00 0 S
+Rule Zion 2014 only - Sep 28 2:00 0 S
+Rule Zion 2015 only - Sep 20 2:00 0 S
+Rule Zion 2016 only - Apr 1 2:00 1:00 D
+Rule Zion 2016 only - Oct 9 2:00 0 S
+Rule Zion 2017 2021 - Mar Fri>=26 2:00 1:00 D
+Rule Zion 2017 only - Sep 24 2:00 0 S
+Rule Zion 2018 only - Sep 16 2:00 0 S
+Rule Zion 2019 only - Oct 6 2:00 0 S
+Rule Zion 2020 only - Sep 27 2:00 0 S
+Rule Zion 2021 only - Sep 12 2:00 0 S
+Rule Zion 2022 only - Apr 1 2:00 1:00 D
+Rule Zion 2022 only - Oct 2 2:00 0 S
+Rule Zion 2023 2032 - Mar Fri>=26 2:00 1:00 D
+Rule Zion 2023 only - Sep 24 2:00 0 S
+Rule Zion 2024 only - Oct 6 2:00 0 S
+Rule Zion 2025 only - Sep 28 2:00 0 S
+Rule Zion 2026 only - Sep 20 2:00 0 S
+Rule Zion 2027 only - Oct 10 2:00 0 S
+Rule Zion 2028 only - Sep 24 2:00 0 S
+Rule Zion 2029 only - Sep 16 2:00 0 S
+Rule Zion 2030 only - Oct 6 2:00 0 S
+Rule Zion 2031 only - Sep 21 2:00 0 S
+Rule Zion 2032 only - Sep 12 2:00 0 S
+Rule Zion 2033 only - Apr 1 2:00 1:00 D
+Rule Zion 2033 only - Oct 2 2:00 0 S
+Rule Zion 2034 2037 - Mar Fri>=26 2:00 1:00 D
+Rule Zion 2034 only - Sep 17 2:00 0 S
+Rule Zion 2035 only - Oct 7 2:00 0 S
+Rule Zion 2036 only - Sep 28 2:00 0 S
+Rule Zion 2037 only - Sep 13 2:00 0 S
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Jerusalem 2:20:56 - LMT 1880
+ 2:20:40 - JMT 1918 # Jerusalem Mean Time?
+ 2:00 Zion I%sT
+
+
+
+###############################################################################
+
+# Japan
+
+# `9:00' and `JST' is from Guy Harris.
+
+# From Paul Eggert (1995-03-06):
+# Today's _Asahi Evening News_ (page 4) reports that Japan had
+# daylight saving between 1948 and 1951, but ``the system was discontinued
+# because the public believed it would lead to longer working hours.''
+
+# From Mayumi Negishi in the 2005-08-10 Japan Times
+# <http://www.japantimes.co.jp/cgi-bin/getarticle.pl5?nn20050810f2.htm>:
+# Occupation authorities imposed daylight-saving time on Japan on
+# [1948-05-01].... But lack of prior debate and the execution of
+# daylight-saving time just three days after the bill was passed generated
+# deep hatred of the concept.... The Diet unceremoniously passed a bill to
+# dump the unpopular system in October 1951, less than a month after the San
+# Francisco Peace Treaty was signed. (A government poll in 1951 showed 53%
+# of the Japanese wanted to scrap daylight-saving time, as opposed to 30% who
+# wanted to keep it.)
+
+# From Paul Eggert (2006-03-22):
+# Shanks & Pottenger write that DST in Japan during those years was as follows:
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Japan 1948 only - May Sun>=1 2:00 1:00 D
+Rule Japan 1948 1951 - Sep Sat>=8 2:00 0 S
+Rule Japan 1949 only - Apr Sun>=1 2:00 1:00 D
+Rule Japan 1950 1951 - May Sun>=1 2:00 1:00 D
+# but the only locations using it (for birth certificates, presumably, since
+# their audience is astrologers) were US military bases. For now, assume
+# that for most purposes daylight-saving time was observed; otherwise, what
+# would have been the point of the 1951 poll?
+
+# From Hideyuki Suzuki (1998-11-09):
+# 'Tokyo' usually stands for the former location of Tokyo Astronomical
+# Observatory: E 139 44' 40".90 (9h 18m 58s.727), N 35 39' 16".0.
+# This data is from 'Rika Nenpyou (Chronological Scientific Tables) 1996'
+# edited by National Astronomical Observatory of Japan....
+# JST (Japan Standard Time) has been used since 1888-01-01 00:00 (JST).
+# The law is enacted on 1886-07-07.
+
+# From Hideyuki Suzuki (1998-11-16):
+# The ordinance No. 51 (1886) established "standard time" in Japan,
+# which stands for the time on E 135 degree.
+# In the ordinance No. 167 (1895), "standard time" was renamed to "central
+# standard time". And the same ordinance also established "western standard
+# time", which stands for the time on E 120 degree.... But "western standard
+# time" was abolished in the ordinance No. 529 (1937). In the ordinance No.
+# 167, there is no mention regarding for what place western standard time is
+# standard....
+#
+# I wrote "ordinance" above, but I don't know how to translate.
+# In Japanese it's "chokurei", which means ordinance from emperor.
+
+# Shanks & Pottenger claim JST in use since 1896, and that a few
+# places (e.g. Ishigaki) use +0800; go with Suzuki. Guess that all
+# ordinances took effect on Jan 1.
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Tokyo 9:18:59 - LMT 1887 Dec 31 15:00u
+ 9:00 - JST 1896
+ 9:00 - CJT 1938
+ 9:00 Japan J%sT
+# Since 1938, all Japanese possessions have been like Asia/Tokyo.
+
+# Jordan
+#
+# From <a href="http://star.arabia.com/990701/JO9.html">
+# Jordan Week (1999-07-01) </a> via Steffen Thorsen (1999-09-09):
+# Clocks in Jordan were forwarded one hour on Wednesday at midnight,
+# in accordance with the government's decision to implement summer time
+# all year round.
+#
+# From <a href="http://star.arabia.com/990930/JO9.html">
+# Jordan Week (1999-09-30) </a> via Steffen Thorsen (1999-11-09):
+# Winter time starts today Thursday, 30 September. Clocks will be turned back
+# by one hour. This is the latest government decision and it's final!
+# The decision was taken because of the increase in working hours in
+# government's departments from six to seven hours.
+#
+# From Paul Eggert (2005-11-22):
+# Starting 2003 transitions are from Steffen Thorsen's web site timeanddate.com.
+#
+# From Steffen Thorsen (2005-11-23):
+# For Jordan I have received multiple independent user reports every year
+# about DST end dates, as the end-rule is different every year.
+#
+# From Steffen Thorsen (2006-10-01), after a heads-up from Hilal Malawi:
+# http://www.petranews.gov.jo/nepras/2006/Sep/05/4000.htm
+# "Jordan will switch to winter time on Friday, October 27".
+#
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Jordan 1973 only - Jun 6 0:00 1:00 S
+Rule Jordan 1973 1975 - Oct 1 0:00 0 -
+Rule Jordan 1974 1977 - May 1 0:00 1:00 S
+Rule Jordan 1976 only - Nov 1 0:00 0 -
+Rule Jordan 1977 only - Oct 1 0:00 0 -
+Rule Jordan 1978 only - Apr 30 0:00 1:00 S
+Rule Jordan 1978 only - Sep 30 0:00 0 -
+Rule Jordan 1985 only - Apr 1 0:00 1:00 S
+Rule Jordan 1985 only - Oct 1 0:00 0 -
+Rule Jordan 1986 1988 - Apr Fri>=1 0:00 1:00 S
+Rule Jordan 1986 1990 - Oct Fri>=1 0:00 0 -
+Rule Jordan 1989 only - May 8 0:00 1:00 S
+Rule Jordan 1990 only - Apr 27 0:00 1:00 S
+Rule Jordan 1991 only - Apr 17 0:00 1:00 S
+Rule Jordan 1991 only - Sep 27 0:00 0 -
+Rule Jordan 1992 only - Apr 10 0:00 1:00 S
+Rule Jordan 1992 1993 - Oct Fri>=1 0:00 0 -
+Rule Jordan 1993 1998 - Apr Fri>=1 0:00 1:00 S
+Rule Jordan 1994 only - Sep Fri>=15 0:00 0 -
+Rule Jordan 1995 1998 - Sep Fri>=15 0:00s 0 -
+Rule Jordan 1999 only - Jul 1 0:00s 1:00 S
+Rule Jordan 1999 2002 - Sep lastThu 0:00s 0 -
+Rule Jordan 2000 max - Mar lastThu 0:00s 1:00 S
+Rule Jordan 2003 only - Oct 24 0:00s 0 -
+Rule Jordan 2004 only - Oct 15 0:00s 0 -
+Rule Jordan 2005 only - Sep lastFri 0:00s 0 -
+Rule Jordan 2006 max - Oct lastFri 0:00s 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Amman 2:23:44 - LMT 1931
+ 2:00 Jordan EE%sT
+
+
+# Kazakhstan
+
+# From Paul Eggert (1996-11-22):
+# Andrew Evtichov (1996-04-13) writes that Kazakhstan
+# stayed in sync with Moscow after 1990, and that Aqtobe (formerly Aktyubinsk)
+# and Aqtau (formerly Shevchenko) are the largest cities in their zones.
+# Guess that Aqtau and Aqtobe diverged in 1995, since that's the first time
+# IATA SSIM mentions a third time zone in Kazakhstan.
+
+# From Paul Eggert (2006-03-22):
+# German Iofis, ELSI, Almaty (2001-10-09) reports that Kazakhstan uses
+# RussiaAsia rules, instead of switching at 00:00 as the IATA has it.
+# Go with Shanks & Pottenger, who have them always using RussiaAsia rules.
+# Also go with the following claims of Shanks & Pottenger:
+#
+# - Kazakhstan did not observe DST in 1991.
+# - Qyzylorda switched from +5:00 to +6:00 on 1992-01-19 02:00.
+# - Oral switched from +5:00 to +4:00 in spring 1989.
+
+# <a href="http://www.kazsociety.org.uk/news/2005/03/30.htm">
+# From Kazakhstan Embassy's News Bulletin #11 (2005-03-21):
+# </a>
+# The Government of Kazakhstan passed a resolution March 15 abolishing
+# daylight saving time citing lack of economic benefits and health
+# complications coupled with a decrease in productivity.
+#
+# From Branislav Kojic (in Astana) via Gwillim Law (2005-06-28):
+# ... what happened was that the former Kazakhstan Eastern time zone
+# was "blended" with the Central zone. Therefore, Kazakhstan now has
+# two time zones, and difference between them is one hour. The zone
+# closer to UTC is the former Western zone (probably still called the
+# same), encompassing four provinces in the west: Aqtobe, Atyrau,
+# Mangghystau, and West Kazakhstan. The other zone encompasses
+# everything else.... I guess that would make Kazakhstan time zones
+# de jure UTC+5 and UTC+6 respectively.
+
+#
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+#
+# Almaty (formerly Alma-Ata), representing most locations in Kazakhstan
+Zone Asia/Almaty 5:07:48 - LMT 1924 May 2 # or Alma-Ata
+ 5:00 - ALMT 1930 Jun 21 # Alma-Ata Time
+ 6:00 RussiaAsia ALM%sT 1991
+ 6:00 - ALMT 1992
+ 6:00 RussiaAsia ALM%sT 2005 Mar 15
+ 6:00 - ALMT
+# Qyzylorda (aka Kyzylorda, Kizilorda, Kzyl-Orda, etc.)
+Zone Asia/Qyzylorda 4:21:52 - LMT 1924 May 2
+ 4:00 - KIZT 1930 Jun 21 # Kizilorda Time
+ 5:00 - KIZT 1981 Apr 1
+ 5:00 1:00 KIZST 1981 Oct 1
+ 6:00 - KIZT 1982 Apr 1
+ 5:00 RussiaAsia KIZ%sT 1991
+ 5:00 - KIZT 1991 Dec 16 # independence
+ 5:00 - QYZT 1992 Jan 19 2:00
+ 6:00 RussiaAsia QYZ%sT 2005 Mar 15
+ 6:00 - QYZT
+# Aqtobe (aka Aktobe, formerly Akt'ubinsk)
+Zone Asia/Aqtobe 3:48:40 - LMT 1924 May 2
+ 4:00 - AKTT 1930 Jun 21 # Aktyubinsk Time
+ 5:00 - AKTT 1981 Apr 1
+ 5:00 1:00 AKTST 1981 Oct 1
+ 6:00 - AKTT 1982 Apr 1
+ 5:00 RussiaAsia AKT%sT 1991
+ 5:00 - AKTT 1991 Dec 16 # independence
+ 5:00 RussiaAsia AQT%sT 2005 Mar 15 # Aqtobe Time
+ 5:00 - AQTT
+# Mangghystau
+# Aqtau was not founded until 1963, but it represents an inhabited region,
+# so include time stamps before 1963.
+Zone Asia/Aqtau 3:21:04 - LMT 1924 May 2
+ 4:00 - FORT 1930 Jun 21 # Fort Shevchenko T
+ 5:00 - FORT 1963
+ 5:00 - SHET 1981 Oct 1 # Shevchenko Time
+ 6:00 - SHET 1982 Apr 1
+ 5:00 RussiaAsia SHE%sT 1991
+ 5:00 - SHET 1991 Dec 16 # independence
+ 5:00 RussiaAsia AQT%sT 1995 Mar lastSun 2:00 # Aqtau Time
+ 4:00 RussiaAsia AQT%sT 2005 Mar 15
+ 5:00 - AQTT
+# West Kazakhstan
+Zone Asia/Oral 3:25:24 - LMT 1924 May 2 # or Ural'sk
+ 4:00 - URAT 1930 Jun 21 # Ural'sk time
+ 5:00 - URAT 1981 Apr 1
+ 5:00 1:00 URAST 1981 Oct 1
+ 6:00 - URAT 1982 Apr 1
+ 5:00 RussiaAsia URA%sT 1989 Mar 26 2:00
+ 4:00 RussiaAsia URA%sT 1991
+ 4:00 - URAT 1991 Dec 16 # independence
+ 4:00 RussiaAsia ORA%sT 2005 Mar 15 # Oral Time
+ 5:00 - ORAT
+
+# Kyrgyzstan (Kirgizstan)
+# Transitions through 1991 are from Shanks & Pottenger.
+
+# From Paul Eggert (2005-08-15):
+# According to an article dated today in the Kyrgyzstan Development Gateway
+# <http://eng.gateway.kg/cgi-bin/page.pl?id=1&story_name=doc9979.shtml>
+# Kyrgyzstan is canceling the daylight saving time system. I take the article
+# to mean that they will leave their clocks at 6 hours ahead of UTC.
+# From Malik Abdugaliev (2005-09-21):
+# Our government cancels daylight saving time 6th of August 2005.
+# From 2005-08-12 our GMT-offset is +6, w/o any daylight saving.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Kyrgyz 1992 1996 - Apr Sun>=7 0:00s 1:00 S
+Rule Kyrgyz 1992 1996 - Sep lastSun 0:00 0 -
+Rule Kyrgyz 1997 2005 - Mar lastSun 2:30 1:00 S
+Rule Kyrgyz 1997 2004 - Oct lastSun 2:30 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Bishkek 4:58:24 - LMT 1924 May 2
+ 5:00 - FRUT 1930 Jun 21 # Frunze Time
+ 6:00 RussiaAsia FRU%sT 1991 Mar 31 2:00s
+ 5:00 1:00 FRUST 1991 Aug 31 2:00 # independence
+ 5:00 Kyrgyz KG%sT 2005 Aug 12 # Kyrgyzstan Time
+ 6:00 - KGT
+
+###############################################################################
+
+# Korea (North and South)
+
+# From Annie I. Bang (2006-07-10) in
+# <http://www.koreaherald.co.kr/SITE/data/html_dir/2006/07/10/200607100012.asp>:
+# The Ministry of Commerce, Industry and Energy has already
+# commissioned a research project [to reintroduce DST] and has said
+# the system may begin as early as 2008.... Korea ran a daylight
+# saving program from 1949-61 but stopped it during the 1950-53 Korean War.
+
+# From Shanks & Pottenger:
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule ROK 1960 only - May 15 0:00 1:00 D
+Rule ROK 1960 only - Sep 13 0:00 0 S
+Rule ROK 1987 1988 - May Sun>=8 0:00 1:00 D
+Rule ROK 1987 1988 - Oct Sun>=8 0:00 0 S
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Seoul 8:27:52 - LMT 1890
+ 8:30 - KST 1904 Dec
+ 9:00 - KST 1928
+ 8:30 - KST 1932
+ 9:00 - KST 1954 Mar 21
+ 8:00 ROK K%sT 1961 Aug 10
+ 8:30 - KST 1968 Oct
+ 9:00 ROK K%sT
+Zone Asia/Pyongyang 8:23:00 - LMT 1890
+ 8:30 - KST 1904 Dec
+ 9:00 - KST 1928
+ 8:30 - KST 1932
+ 9:00 - KST 1954 Mar 21
+ 8:00 - KST 1961 Aug 10
+ 9:00 - KST
+
+###############################################################################
+
+# Kuwait
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# From the Arab Times (2007-03-14):
+# The Civil Service Commission (CSC) has approved a proposal forwarded
+# by MP Ahmad Baqer on implementing the daylight saving time (DST) in
+# Kuwait starting from April until the end of Sept this year, reports Al-Anba.
+# <http://www.arabtimesonline.com/arabtimes/kuwait/Viewdet.asp?ID=9950>.
+# From Paul Eggert (2007-03-29):
+# We don't know the details, or whether the approval means it'll happen,
+# so for now we assume no DST.
+Zone Asia/Kuwait 3:11:56 - LMT 1950
+ 3:00 - AST
+
+# Laos
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Vientiane 6:50:24 - LMT 1906 Jun 9 # or Viangchan
+ 7:06:20 - SMT 1911 Mar 11 0:01 # Saigon MT?
+ 7:00 - ICT 1912 May
+ 8:00 - ICT 1931 May
+ 7:00 - ICT
+
+# Lebanon
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Lebanon 1920 only - Mar 28 0:00 1:00 S
+Rule Lebanon 1920 only - Oct 25 0:00 0 -
+Rule Lebanon 1921 only - Apr 3 0:00 1:00 S
+Rule Lebanon 1921 only - Oct 3 0:00 0 -
+Rule Lebanon 1922 only - Mar 26 0:00 1:00 S
+Rule Lebanon 1922 only - Oct 8 0:00 0 -
+Rule Lebanon 1923 only - Apr 22 0:00 1:00 S
+Rule Lebanon 1923 only - Sep 16 0:00 0 -
+Rule Lebanon 1957 1961 - May 1 0:00 1:00 S
+Rule Lebanon 1957 1961 - Oct 1 0:00 0 -
+Rule Lebanon 1972 only - Jun 22 0:00 1:00 S
+Rule Lebanon 1972 1977 - Oct 1 0:00 0 -
+Rule Lebanon 1973 1977 - May 1 0:00 1:00 S
+Rule Lebanon 1978 only - Apr 30 0:00 1:00 S
+Rule Lebanon 1978 only - Sep 30 0:00 0 -
+Rule Lebanon 1984 1987 - May 1 0:00 1:00 S
+Rule Lebanon 1984 1991 - Oct 16 0:00 0 -
+Rule Lebanon 1988 only - Jun 1 0:00 1:00 S
+Rule Lebanon 1989 only - May 10 0:00 1:00 S
+Rule Lebanon 1990 1992 - May 1 0:00 1:00 S
+Rule Lebanon 1992 only - Oct 4 0:00 0 -
+Rule Lebanon 1993 max - Mar lastSun 0:00 1:00 S
+Rule Lebanon 1993 1998 - Sep lastSun 0:00 0 -
+Rule Lebanon 1999 max - Oct lastSun 0:00 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Beirut 2:22:00 - LMT 1880
+ 2:00 Lebanon EE%sT
+
+# Malaysia
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule NBorneo 1935 1941 - Sep 14 0:00 0:20 TS # one-Third Summer
+Rule NBorneo 1935 1941 - Dec 14 0:00 0 -
+#
+# peninsular Malaysia
+# The data here are taken from Mok Ly Yng (2003-10-30)
+# <http://www.math.nus.edu.sg/aslaksen/teaching/timezone.html>.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Kuala_Lumpur 6:46:46 - LMT 1901 Jan 1
+ 6:55:25 - SMT 1905 Jun 1 # Singapore M.T.
+ 7:00 - MALT 1933 Jan 1 # Malaya Time
+ 7:00 0:20 MALST 1936 Jan 1
+ 7:20 - MALT 1941 Sep 1
+ 7:30 - MALT 1942 Feb 16
+ 9:00 - JST 1945 Sep 12
+ 7:30 - MALT 1982 Jan 1
+ 8:00 - MYT # Malaysia Time
+# Sabah & Sarawak
+# From Paul Eggert (2006-03-22):
+# The data here are mostly from Shanks & Pottenger, but the 1942, 1945 and 1982
+# transition dates are from Mok Ly Yng.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Kuching 7:21:20 - LMT 1926 Mar
+ 7:30 - BORT 1933 # Borneo Time
+ 8:00 NBorneo BOR%sT 1942 Feb 16
+ 9:00 - JST 1945 Sep 12
+ 8:00 - BORT 1982 Jan 1
+ 8:00 - MYT
+
+# Maldives
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Indian/Maldives 4:54:00 - LMT 1880 # Male
+ 4:54:00 - MMT 1960 # Male Mean Time
+ 5:00 - MVT # Maldives Time
+
+# Mongolia
+
+# Shanks & Pottenger say that Mongolia has three time zones, but
+# usno1995 and the CIA map Standard Time Zones of the World (2005-03)
+# both say that it has just one.
+
+# From Oscar van Vlijmen (1999-12-11):
+# <a href="http://www.mongoliatourism.gov.mn/general.htm">
+# General Information Mongolia
+# </a> (1999-09)
+# "Time: Mongolia has two time zones. Three westernmost provinces of
+# Bayan-Ulgii, Uvs, and Hovd are one hour earlier than the capital city, and
+# the rest of the country follows the Ulaanbaatar time, which is UTC/GMT plus
+# eight hours."
+
+# From Rives McDow (1999-12-13):
+# Mongolia discontinued the use of daylight savings time in 1999; 1998
+# being the last year it was implemented. The dates of implementation I am
+# unsure of, but most probably it was similar to Russia, except for the time
+# of implementation may have been different....
+# Some maps in the past have indicated that there was an additional time
+# zone in the eastern part of Mongolia, including the provinces of Dornod,
+# Suhbaatar, and possibly Khentij.
+
+# From Paul Eggert (1999-12-15):
+# Naming and spelling is tricky in Mongolia.
+# We'll use Hovd (also spelled Chovd and Khovd) to represent the west zone;
+# the capital of the Hovd province is sometimes called Hovd, sometimes Dund-Us,
+# and sometimes Jirgalanta (with variant spellings), but the name Hovd
+# is good enough for our purposes.
+
+# From Rives McDow (2001-05-13):
+# In addition to Mongolia starting daylight savings as reported earlier
+# (adopted DST on 2001-04-27 02:00 local time, ending 2001-09-28),
+# there are three time zones.
+#
+# Provinces [at 7:00]: Bayan-ulgii, Uvs, Khovd, Zavkhan, Govi-Altai
+# Provinces [at 8:00]: Khovsgol, Bulgan, Arkhangai, Khentii, Tov,
+# Bayankhongor, Ovorkhangai, Dundgovi, Dornogovi, Omnogovi
+# Provinces [at 9:00]: Dornod, Sukhbaatar
+#
+# [The province of Selenge is omitted from the above lists.]
+
+# From Ganbold Ts., Ulaanbaatar (2004-04-17):
+# Daylight saving occurs at 02:00 local time last Saturday of March.
+# It will change back to normal at 02:00 local time last Saturday of
+# September.... As I remember this rule was changed in 2001.
+#
+# From Paul Eggert (2004-04-17):
+# For now, assume Rives McDow's informant got confused about Friday vs
+# Saturday, and that his 2001 dates should have 1 added to them.
+
+# From Paul Eggert (2005-07-26):
+# We have wildly conflicting information about Mongolia's time zones.
+# Bill Bonnet (2005-05-19) reports that the US Embassy in Ulaanbaatar says
+# there is only one time zone and that DST is observed, citing Microsoft
+# Windows XP as the source. Risto Nykanen (2005-05-16) reports that
+# travelmongolia.org says there are two time zones (UTC+7, UTC+8) with no DST.
+# Oscar van Vlijmen (2005-05-20) reports that the Mongolian Embassy in
+# Washington, DC says there are two time zones, with DST observed.
+# He also found
+# <http://ubpost.mongolnews.mn/index.php?subaction=showcomments&id=1111634894&archive=&start_from=&ucat=1&>
+# which also says that there is DST, and which has a comment by "Toddius"
+# (2005-03-31 06:05 +0700) saying "Mongolia actually has 3.5 time zones.
+# The West (OLGII) is +7 GMT, most of the country is ULAT is +8 GMT
+# and some Eastern provinces are +9 GMT but Sukhbaatar Aimag is SUHK +8.5 GMT.
+# The SUKH timezone is new this year, it is one of the few things the
+# parliament passed during the tumultuous winter session."
+# For now, let's ignore this information, until we have more confirmation.
+
+# From Ganbold Ts. (2007-02-26):
+# Parliament of Mongolia has just changed the daylight-saving rule in February.
+# They decided not to adopt daylight-saving time....
+# http://www.mongolnews.mn/index.php?module=unuudur&sec=view&id=15742
+
+# From Deborah Goldsmith (2008-03-30):
+# We received a bug report claiming that the tz database UTC offset for
+# Asia/Choibalsan (GMT+09:00) is incorrect, and that it should be GMT
+# +08:00 instead. Different sources appear to disagree with the tz
+# database on this, e.g.:
+#
+# <a href="http://www.timeanddate.com/worldclock/city.html?n=1026">
+# http://www.timeanddate.com/worldclock/city.html?n=1026
+# </a>
+# <a href="http://www.worldtimeserver.com/current_time_in_MN.aspx">
+# http://www.worldtimeserver.com/current_time_in_MN.aspx
+# </a>
+#
+# both say GMT+08:00.
+
+# From Steffen Thorsen (2008-03-31):
+# eznis airways, which operates several domestic flights, has a flight
+# schedule here:
+# <a href="http://www.eznis.com/Container.jsp?id=112">
+# http://www.eznis.com/Container.jsp?id=112
+# </a>
+# (click the English flag for English)
+#
+# There it appears that flights between Choibalsan and Ulaanbatar arrive
+# about 1:35 - 1:50 hours later in local clock time, no matter the
+# direction, while Ulaanbaatar-Khvod takes 2 hours in the Eastern
+# direction and 3:35 back, which indicates that Ulaanbatar and Khvod are
+# in different time zones (like we know about), while Choibalsan and
+# Ulaanbatar are in the same time zone (correction needed).
+
+# From Arthur David Olson (2008-05-19):
+# Assume that Choibalsan is indeed offset by 8:00.
+# XXX--in the absence of better information, assume that transition
+# was at the start of 2008-03-31 (the day of Steffen Thorsen's report);
+# this is almost surely wrong.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Mongol 1983 1984 - Apr 1 0:00 1:00 S
+Rule Mongol 1983 only - Oct 1 0:00 0 -
+# Shanks & Pottenger and IATA SSIM say 1990s switches occurred at 00:00,
+# but McDow says the 2001 switches occurred at 02:00. Also, IATA SSIM
+# (1996-09) says 1996-10-25. Go with Shanks & Pottenger through 1998.
+#
+# Shanks & Pottenger say that the Sept. 1984 through Sept. 1990 switches
+# in Choibalsan (more precisely, in Dornod and Sukhbaatar) took place
+# at 02:00 standard time, not at 00:00 local time as in the rest of
+# the country. That would be odd, and possibly is a result of their
+# correction of 02:00 (in the previous edition) not being done correctly
+# in the latest edition; so ignore it for now.
+
+Rule Mongol 1985 1998 - Mar lastSun 0:00 1:00 S
+Rule Mongol 1984 1998 - Sep lastSun 0:00 0 -
+# IATA SSIM (1999-09) says Mongolia no longer observes DST.
+Rule Mongol 2001 only - Apr lastSat 2:00 1:00 S
+Rule Mongol 2001 2006 - Sep lastSat 2:00 0 -
+Rule Mongol 2002 2006 - Mar lastSat 2:00 1:00 S
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Hovd, a.k.a. Chovd, Dund-Us, Dzhargalant, Khovd, Jirgalanta
+Zone Asia/Hovd 6:06:36 - LMT 1905 Aug
+ 6:00 - HOVT 1978 # Hovd Time
+ 7:00 Mongol HOV%sT
+# Ulaanbaatar, a.k.a. Ulan Bataar, Ulan Bator, Urga
+Zone Asia/Ulaanbaatar 7:07:32 - LMT 1905 Aug
+ 7:00 - ULAT 1978 # Ulaanbaatar Time
+ 8:00 Mongol ULA%sT
+# Choibalsan, a.k.a. Bajan Tuemen, Bajan Tumen, Chojbalsan,
+# Choybalsan, Sanbejse, Tchoibalsan
+Zone Asia/Choibalsan 7:38:00 - LMT 1905 Aug
+ 7:00 - ULAT 1978
+ 8:00 - ULAT 1983 Apr
+ 9:00 Mongol CHO%sT 2008 Mar 31 # Choibalsan Time
+ 8:00 Mongol CHO%sT
+
+# Nepal
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Katmandu 5:41:16 - LMT 1920
+ 5:30 - IST 1986
+ 5:45 - NPT # Nepal Time
+
+# Oman
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Muscat 3:54:20 - LMT 1920
+ 4:00 - GST
+
+# Pakistan
+
+# From Rives McDow (2002-03-13):
+# I have been advised that Pakistan has decided to adopt dst on a
+# TRIAL basis for one year, starting 00:01 local time on April 7, 2002
+# and ending at 00:01 local time October 6, 2002. This is what I was
+# told, but I believe that the actual time of change may be 00:00; the
+# 00:01 was to make it clear which day it was on.
+
+# From Paul Eggert (2002-03-15):
+# Jesper Norgaard found this URL:
+# http://www.pak.gov.pk/public/news/app/app06_dec.htm
+# (dated 2001-12-06) which says that the Cabinet adopted a scheme "to
+# advance the clocks by one hour on the night between the first
+# Saturday and Sunday of April and revert to the original position on
+# 15th October each year". This agrees with McDow's 04-07 at 00:00,
+# but disagrees about the October transition, and makes it sound like
+# it's not on a trial basis. Also, the "between the first Saturday
+# and Sunday of April" phrase, if taken literally, means that the
+# transition takes place at 00:00 on the first Sunday on or after 04-02.
+
+# From Paul Eggert (2003-02-09):
+# DAWN <http://www.dawn.com/2002/10/06/top13.htm> reported on 2002-10-05
+# that 2002 DST ended that day at midnight. Go with McDow for now.
+
+# From Steffen Thorsen (2003-03-14):
+# According to http://www.dawn.com/2003/03/07/top15.htm
+# there will be no DST in Pakistan this year:
+#
+# ISLAMABAD, March 6: Information and Media Development Minister Sheikh
+# Rashid Ahmed on Thursday said the cabinet had reversed a previous
+# decision to advance clocks by one hour in summer and put them back by
+# one hour in winter with the aim of saving light hours and energy.
+#
+# The minister told a news conference that the experiment had rather
+# shown 8 per cent higher consumption of electricity.
+
+# From Alex Krivenyshev (2008-05-15):
+#
+# Here is an article that Pakistan plan to introduce Daylight Saving Time
+# on June 1, 2008 for 3 months.
+#
+# "... The federal cabinet on Wednesday announced a new conservation plan to help
+# reduce load shedding by approving the closure of commercial centres at 9pm and
+# moving clocks forward by one hour for the next three months.
+# ...."
+#
+# <a href="http://www.worldtimezone.net/dst_news/dst_news_pakistan01.html">
+# http://www.worldtimezone.net/dst_news/dst_news_pakistan01.html
+# </a>
+# OR
+# <a href="http://www.dailytimes.com.pk/default.asp?page=2008%5C05%5C15%5Cstory_15-5-2008_pg1_4">
+# http://www.dailytimes.com.pk/default.asp?page=2008%5C05%5C15%5Cstory_15-5-2008_pg1_4
+# </a>
+
+# From Arthur David Olson (2008-05-19):
+# XXX--midnight transitions is a guess; 2008 only is a guess.
+
+# From Alexander Krivenyshev (2008-08-28):
+# Pakistan government has decided to keep the watches one-hour advanced
+# for another 2 months--plan to return to Standard Time on October 31
+# instead of August 31.
+#
+# <a href="http://www.worldtimezone.com/dst_news/dst_news_pakistan02.html">
+# http://www.worldtimezone.com/dst_news/dst_news_pakistan02.html
+# </a>
+# OR
+# <a href="http://dailymailnews.com/200808/28/news/dmbrn03.html">
+# http://dailymailnews.com/200808/28/news/dmbrn03.html
+# </a>
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Pakistan 2002 only - Apr Sun>=2 0:01 1:00 S
+Rule Pakistan 2002 only - Oct Sun>=2 0:01 0 -
+Rule Pakistan 2008 only - Jun 1 0:00 1:00 S
+Rule Pakistan 2008 only - Nov 1 0:00 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Karachi 4:28:12 - LMT 1907
+ 5:30 - IST 1942 Sep
+ 5:30 1:00 IST 1945 Oct 15
+ 5:30 - IST 1951 Sep 30
+ 5:00 - KART 1971 Mar 26 # Karachi Time
+ 5:00 Pakistan PK%sT # Pakistan Time
+
+# Palestine
+
+# From Amos Shapir (1998-02-15):
+#
+# From 1917 until 1948-05-15, all of Palestine, including the parts now
+# known as the Gaza Strip and the West Bank, was under British rule.
+# Therefore the rules given for Israel for that period, apply there too...
+#
+# The Gaza Strip was under Egyptian rule between 1948-05-15 until 1967-06-05
+# (except a short occupation by Israel from 1956-11 till 1957-03, but no
+# time zone was affected then). It was never formally annexed to Egypt,
+# though.
+#
+# The rest of Palestine was under Jordanian rule at that time, formally
+# annexed in 1950 as the West Bank (and the word "Trans" was dropped from
+# the country's previous name of "the Hashemite Kingdom of the
+# Trans-Jordan"). So the rules for Jordan for that time apply. Major
+# towns in that area are Nablus (Shchem), El-Halil (Hebron), Ramallah, and
+# East Jerusalem.
+#
+# Both areas were occupied by Israel in June 1967, but not annexed (except
+# for East Jerusalem). They were on Israel time since then; there might
+# have been a Military Governor's order about time zones, but I'm not aware
+# of any (such orders may have been issued semi-annually whenever summer
+# time was in effect, but maybe the legal aspect of time was just neglected).
+#
+# The Palestinian Authority was established in 1993, and got hold of most
+# towns in the West Bank and Gaza by 1995. I know that in order to
+# demonstrate...independence, they have been switching to
+# summer time and back on a different schedule than Israel's, but I don't
+# know when this was started, or what algorithm is used (most likely the
+# Jordanian one).
+#
+# To summarize, the table should probably look something like that:
+#
+# Area \ when | 1918-1947 | 1948-1967 | 1967-1995 | 1996-
+# ------------+-----------+-----------+-----------+-----------
+# Israel | Zion | Zion | Zion | Zion
+# West bank | Zion | Jordan | Zion | Jordan
+# Gaza | Zion | Egypt | Zion | Jordan
+#
+# I guess more info may be available from the PA's web page (if/when they
+# have one).
+
+# From Paul Eggert (2006-03-22):
+# Shanks & Pottenger write that Gaza did not observe DST until 1957, but go
+# with Shapir and assume that it observed DST from 1940 through 1947,
+# and that it used Jordanian rules starting in 1996.
+# We don't yet need a separate entry for the West Bank, since
+# the only differences between it and Gaza that we know about
+# occurred before our cutoff date of 1970.
+# However, as we get more information, we may need to add entries
+# for parts of the West Bank as they transitioned from Israel's rules
+# to Palestine's rules. If you have more info about this, please
+# send it to tz@elsie.nci.nih.gov for incorporation into future editions.
+
+# From IINS News Service - Israel - 1998-03-23 10:38:07 Israel time,
+# forwarded by Ephraim Silverberg:
+#
+# Despite the fact that Israel changed over to daylight savings time
+# last week, the PLO Authority (PA) has decided not to turn its clocks
+# one-hour forward at this time. As a sign of independence from Israeli rule,
+# the PA has decided to implement DST in April.
+
+# From Paul Eggert (1999-09-20):
+# Daoud Kuttab writes in
+# <a href="http://www.jpost.com/com/Archive/22.Apr.1999/Opinion/Article-2.html">
+# Holiday havoc
+# </a> (Jerusalem Post, 1999-04-22) that
+# the Palestinian National Authority changed to DST on 1999-04-15.
+# I vaguely recall that they switch back in October (sorry, forgot the source).
+# For now, let's assume that the spring switch was at 24:00,
+# and that they switch at 0:00 on the 3rd Fridays of April and October.
+
+# From Paul Eggert (2005-11-22):
+# Starting 2004 transitions are from Steffen Thorsen's web site timeanddate.com.
+
+# From Steffen Thorsen (2005-11-23):
+# A user from Gaza reported that Gaza made the change early because of
+# the Ramadan. Next year Ramadan will be even earlier, so I think
+# there is a good chance next year's end date will be around two weeks
+# earlier--the same goes for Jordan.
+
+# From Steffen Thorsen (2006-08-17):
+# I was informed by a user in Bethlehem that in Bethlehem it started the
+# same day as Israel, and after checking with other users in the area, I
+# was informed that they started DST one day after Israel. I was not
+# able to find any authoritative sources at the time, nor details if
+# Gaza changed as well, but presumed Gaza to follow the same rules as
+# the West Bank.
+
+# From Steffen Thorsen (2006-09-26):
+# according to the Palestine News Network (2006-09-19):
+# http://english.pnn.ps/index.php?option=com_content&task=view&id=596&Itemid=5
+# > The Council of Ministers announced that this year its winter schedule
+# > will begin early, as of midnight Thursday. It is also time to turn
+# > back the clocks for winter. Friday will begin an hour late this week.
+# I guess it is likely that next year's date will be moved as well,
+# because of the Ramadan.
+
+# From Jesper Norgaard Welen (2007-09-18):
+# According to Steffen Thorsen's web site the Gaza Strip and the rest of the
+# Palestinian territories left DST early on 13.th. of September at 2:00.
+
+# From Paul Eggert (2007-09-20):
+# My understanding is that Gaza and the West Bank disagree even over when
+# the weekend is (Thursday+Friday versus Friday+Saturday), so I'd be a bit
+# surprised if they agreed about DST. But for now, assume they agree.
+# For lack of better information, predict that future changes will be
+# the 2nd Thursday of September at 02:00.
+
+# From Alexander Krivenyshev (2008-08-28):
+# Here is an article, that Mideast running on different clocks at Ramadan.
+#
+# Gaza Strip (as Egypt) ended DST at midnight Thursday (Aug 28, 2008), while
+# the West Bank will end Daylight Saving Time at midnight Sunday (Aug 31, 2008).
+#
+# <a href="http://www.guardian.co.uk/world/feedarticle/7759001">
+# http://www.guardian.co.uk/world/feedarticle/7759001
+# </a>
+# <a href="http://www.abcnews.go.com/International/wireStory?id=5676087">
+# http://www.abcnews.go.com/International/wireStory?id=5676087
+# </a>
+# or
+# <a href="http://www.worldtimezone.com/dst_news/dst_news_gazastrip01.html">
+# http://www.worldtimezone.com/dst_news/dst_news_gazastrip01.html
+# </a>
+
+# The rules for Egypt are stolen from the `africa' file.
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule EgyptAsia 1957 only - May 10 0:00 1:00 S
+Rule EgyptAsia 1957 1958 - Oct 1 0:00 0 -
+Rule EgyptAsia 1958 only - May 1 0:00 1:00 S
+Rule EgyptAsia 1959 1967 - May 1 1:00 1:00 S
+Rule EgyptAsia 1959 1965 - Sep 30 3:00 0 -
+Rule EgyptAsia 1966 only - Oct 1 3:00 0 -
+
+Rule Palestine 1999 2005 - Apr Fri>=15 0:00 1:00 S
+Rule Palestine 1999 2003 - Oct Fri>=15 0:00 0 -
+Rule Palestine 2004 only - Oct 1 1:00 0 -
+Rule Palestine 2005 only - Oct 4 2:00 0 -
+Rule Palestine 2006 max - Apr 1 0:00 1:00 S
+Rule Palestine 2006 only - Sep 22 0:00 0 -
+Rule Palestine 2007 only - Sep Thu>=8 2:00 0 -
+Rule Palestine 2008 max - Aug lastThu 2:00 0 -
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Gaza 2:17:52 - LMT 1900 Oct
+ 2:00 Zion EET 1948 May 15
+ 2:00 EgyptAsia EE%sT 1967 Jun 5
+ 2:00 Zion I%sT 1996
+ 2:00 Jordan EE%sT 1999
+ 2:00 Palestine EE%sT
+
+# Paracel Is
+# no information
+
+# Philippines
+# On 1844-08-16, Narciso Claveria, governor-general of the
+# Philippines, issued a proclamation announcing that 1844-12-30 was to
+# be immediately followed by 1845-01-01. Robert H. van Gent has a
+# transcript of the decree in <http://www.phys.uu.nl/~vgent/idl/idl.htm>.
+# The rest of the data are from Shanks & Pottenger.
+
+# From Paul Eggert (2006-04-25):
+# Tomorrow's Manila Standard reports that the Philippines Department of
+# Trade and Industry is considering adopting DST this June when the
+# rainy season begins. See
+# <http://www.manilastandardtoday.com/?page=politics02_april26_2006>.
+# For now, we'll ignore this, since it's not definite and we lack details.
+#
+# From Jesper Norgaard Welen (2006-04-26):
+# ... claims that Philippines had DST last time in 1990:
+# http://story.philippinetimes.com/p.x/ct/9/id/145be20cc6b121c0/cid/3e5bbccc730d258c/
+# [a story dated 2006-04-25 by Cris Larano of Dow Jones Newswires,
+# but no details]
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Phil 1936 only - Nov 1 0:00 1:00 S
+Rule Phil 1937 only - Feb 1 0:00 0 -
+Rule Phil 1954 only - Apr 12 0:00 1:00 S
+Rule Phil 1954 only - Jul 1 0:00 0 -
+Rule Phil 1978 only - Mar 22 0:00 1:00 S
+Rule Phil 1978 only - Sep 21 0:00 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Manila -15:56:00 - LMT 1844 Dec 31
+ 8:04:00 - LMT 1899 May 11
+ 8:00 Phil PH%sT 1942 May
+ 9:00 - JST 1944 Nov
+ 8:00 Phil PH%sT
+
+# Qatar
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Qatar 3:26:08 - LMT 1920 # Al Dawhah / Doha
+ 4:00 - GST 1972 Jun
+ 3:00 - AST
+
+# Saudi Arabia
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Riyadh 3:06:52 - LMT 1950
+ 3:00 - AST
+
+# Singapore
+# The data here are taken from Mok Ly Yng (2003-10-30)
+# <http://www.math.nus.edu.sg/aslaksen/teaching/timezone.html>.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Singapore 6:55:25 - LMT 1901 Jan 1
+ 6:55:25 - SMT 1905 Jun 1 # Singapore M.T.
+ 7:00 - MALT 1933 Jan 1 # Malaya Time
+ 7:00 0:20 MALST 1936 Jan 1
+ 7:20 - MALT 1941 Sep 1
+ 7:30 - MALT 1942 Feb 16
+ 9:00 - JST 1945 Sep 12
+ 7:30 - MALT 1965 Aug 9 # independence
+ 7:30 - SGT 1982 Jan 1 # Singapore Time
+ 8:00 - SGT
+
+# Spratly Is
+# no information
+
+# Sri Lanka
+# From Paul Eggert (1996-09-03):
+# "Sri Lanka advances clock by an hour to avoid blackout"
+# (www.virtual-pc.com/lankaweb/news/items/240596-2.html, 1996-05-24,
+# no longer available as of 1999-08-17)
+# reported ``the country's standard time will be put forward by one hour at
+# midnight Friday (1830 GMT) `in the light of the present power crisis'.''
+#
+# From Dharmasiri Senanayake, Sri Lanka Media Minister (1996-10-24), as quoted
+# by Shamindra in
+# <a href="news:54rka5$m5h@mtinsc01-mgt.ops.worldnet.att.net">
+# Daily News - Hot News Section (1996-10-26)
+# </a>:
+# With effect from 12.30 a.m. on 26th October 1996
+# Sri Lanka will be six (06) hours ahead of GMT.
+
+# From Jesper Norgaard Welen (2006-04-14), quoting Sri Lanka News Online
+# <http://news.sinhalaya.com/wmview.php?ArtID=11002> (2006-04-13):
+# 0030 hrs on April 15, 2006 (midnight of April 14, 2006 +30 minutes)
+# at present, become 2400 hours of April 14, 2006 (midnight of April 14, 2006).
+
+# From Peter Apps and Ranga Sirila of Reuters (2006-04-12) in:
+# <http://today.reuters.co.uk/news/newsArticle.aspx?type=scienceNews&storyID=2006-04-12T172228Z_01_COL295762_RTRIDST_0_SCIENCE-SRILANKA-TIME-DC.XML>
+# [The Tamil Tigers] never accepted the original 1996 time change and simply
+# kept their clocks set five and a half hours ahead of Greenwich Mean
+# Time (GMT), in line with neighbor India.
+# From Paul Eggert (2006-04-18):
+# People who live in regions under Tamil control can use [TZ='Asia/Kolkata'],
+# as that zone has agreed with the Tamil areas since our cutoff date of 1970.
+
+# From K Sethu (2006-04-25):
+# I think the abbreviation LKT originated from the world of computers at
+# the time of or subsequent to the time zone changes by SL Government
+# twice in 1996 and probably SL Government or its standardization
+# agencies never declared an abbreviation as a national standard.
+#
+# I recollect before the recent change the government annoucemments
+# mentioning it as simply changing Sri Lanka Standard Time or Sri Lanka
+# Time and no mention was made about the abbreviation.
+#
+# If we look at Sri Lanka Department of Government's "Official News
+# Website of Sri Lanka" ... http://www.news.lk/ we can see that they
+# use SLT as abbreviation in time stamp at the beginning of each news
+# item....
+#
+# Within Sri Lanka I think LKT is well known among computer users and
+# adminsitrators. In my opinion SLT may not be a good choice because the
+# nation's largest telcom / internet operator Sri Lanka Telcom is well
+# known by that abbreviation - simply as SLT (there IP domains are
+# slt.lk and sltnet.lk).
+#
+# But if indeed our government has adopted SLT as standard abbreviation
+# (that we have not known so far) then it is better that it be used for
+# all computers.
+
+# From Paul Eggert (2006-04-25):
+# One possibility is that we wait for a bit for the dust to settle down
+# and then see what people actually say in practice.
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Colombo 5:19:24 - LMT 1880
+ 5:19:32 - MMT 1906 # Moratuwa Mean Time
+ 5:30 - IST 1942 Jan 5
+ 5:30 0:30 IHST 1942 Sep
+ 5:30 1:00 IST 1945 Oct 16 2:00
+ 5:30 - IST 1996 May 25 0:00
+ 6:30 - LKT 1996 Oct 26 0:30
+ 6:00 - LKT 2006 Apr 15 0:30
+ 5:30 - IST
+
+# Syria
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Syria 1920 1923 - Apr Sun>=15 2:00 1:00 S
+Rule Syria 1920 1923 - Oct Sun>=1 2:00 0 -
+Rule Syria 1962 only - Apr 29 2:00 1:00 S
+Rule Syria 1962 only - Oct 1 2:00 0 -
+Rule Syria 1963 1965 - May 1 2:00 1:00 S
+Rule Syria 1963 only - Sep 30 2:00 0 -
+Rule Syria 1964 only - Oct 1 2:00 0 -
+Rule Syria 1965 only - Sep 30 2:00 0 -
+Rule Syria 1966 only - Apr 24 2:00 1:00 S
+Rule Syria 1966 1976 - Oct 1 2:00 0 -
+Rule Syria 1967 1978 - May 1 2:00 1:00 S
+Rule Syria 1977 1978 - Sep 1 2:00 0 -
+Rule Syria 1983 1984 - Apr 9 2:00 1:00 S
+Rule Syria 1983 1984 - Oct 1 2:00 0 -
+Rule Syria 1986 only - Feb 16 2:00 1:00 S
+Rule Syria 1986 only - Oct 9 2:00 0 -
+Rule Syria 1987 only - Mar 1 2:00 1:00 S
+Rule Syria 1987 1988 - Oct 31 2:00 0 -
+Rule Syria 1988 only - Mar 15 2:00 1:00 S
+Rule Syria 1989 only - Mar 31 2:00 1:00 S
+Rule Syria 1989 only - Oct 1 2:00 0 -
+Rule Syria 1990 only - Apr 1 2:00 1:00 S
+Rule Syria 1990 only - Sep 30 2:00 0 -
+Rule Syria 1991 only - Apr 1 0:00 1:00 S
+Rule Syria 1991 1992 - Oct 1 0:00 0 -
+Rule Syria 1992 only - Apr 8 0:00 1:00 S
+Rule Syria 1993 only - Mar 26 0:00 1:00 S
+Rule Syria 1993 only - Sep 25 0:00 0 -
+# IATA SSIM (1998-02) says 1998-04-02;
+# (1998-09) says 1999-03-29 and 1999-09-29; (1999-02) says 1999-04-02,
+# 2000-04-02, and 2001-04-02; (1999-09) says 2000-03-31 and 2001-03-31;
+# (2006) says 2006-03-31 and 2006-09-22;
+# for now ignore all these claims and go with Shanks & Pottenger,
+# except for the 2006-09-22 claim (which seems right for Ramadan).
+Rule Syria 1994 1996 - Apr 1 0:00 1:00 S
+Rule Syria 1994 2005 - Oct 1 0:00 0 -
+Rule Syria 1997 1998 - Mar lastMon 0:00 1:00 S
+Rule Syria 1999 2006 - Apr 1 0:00 1:00 S
+# From Stephen Colebourne (2006-09-18):
+# According to IATA data, Syria will change DST on 21st September [21:00 UTC]
+# this year [only].... This is probably related to Ramadan, like Egypt.
+Rule Syria 2006 only - Sep 22 0:00 0 -
+# From Paul Eggert (2007-03-29):
+# Today the AP reported "Syria will switch to summertime at midnight Thursday."
+# http://www.iht.com/articles/ap/2007/03/29/africa/ME-GEN-Syria-Time-Change.php
+Rule Syria 2007 only - Mar lastFri 0:00 1:00 S
+# From Jesper Norgard (2007-10-27):
+# The sister center ICARDA of my work CIMMYT is confirming that Syria DST will
+# not take place 1.st November at 0:00 o'clock but 1.st November at 24:00 or
+# rather Midnight between Thursday and Friday. This does make more sence than
+# having it between Wednesday and Thursday (two workdays in Syria) since the
+# weekend in Syria is not Saturday and Sunday, but Friday and Saturday. So now
+# it is implemented at midnight of the last workday before weekend...
+#
+# From Steffen Thorsen (2007-10-27):
+# Jesper Norgaard Welen wrote:
+#
+# > "Winter local time in Syria will be observed at midnight of Thursday 1
+# > November 2007, and the clock will be put back 1 hour."
+#
+# I found confirmation on this in this gov.sy-article (Arabic):
+# http://wehda.alwehda.gov.sy/_print_veiw.asp?FileName=12521710520070926111247
+#
+# which using Google's translate tools says:
+# Council of Ministers also approved the commencement of work on
+# identifying the winter time as of Friday, 2/11/2007 where the 60th
+# minute delay at midnight Thursday 1/11/2007.
+Rule Syria 2007 only - Nov Fri>=1 0:00 0 -
+
+# From Stephen Colebourne (2008-03-17):
+# For everyone's info, I saw an IATA time zone change for [Syria] for
+# this month (March 2008) in the last day or so...This is the data IATA
+# are now using:
+# Country Time Standard --- DST Start --- --- DST End --- DST
+# Name Zone Variation Time Date Time Date
+# Variation
+# Syrian Arab
+# Republic SY +0200 2200 03APR08 2100 30SEP08 +0300
+# 2200 02APR09 2100 30SEP09 +0300
+# 2200 01APR10 2100 30SEP10 +0300
+
+# From Arthur David Olson (2008-03-17):
+# Here's a link to English-language coverage by the Syrian Arab News
+# Agency (SANA)...
+# <a href="http://www.sana.sy/eng/21/2008/03/11/165173.htm">
+# http://www.sana.sy/eng/21/2008/03/11/165173.htm
+# </a>...which reads (in part) "The Cabinet approved the suggestion of the
+# Ministry of Electricity to begin daylight savings time on Friday April
+# 4th, advancing clocks one hour ahead on midnight of Thursday April 3rd."
+# Since Syria is two hours east of UTC, the 2200 and 2100 transition times
+# shown above match up with midnight in Syria.
+
+# From Arthur David Olson (2008-03-18):
+# My buest guess at a Syrian rule is "the Friday nearest April 1";
+# coding that involves either using a "Mar Fri>=29" construct that old time zone
+# compilers can't handle or having multiple Rules (a la Israel).
+# For now, use "Apr Fri>=1", and go with IATA on a uniform Sep 30 end.
+
+# From Steffen Thorsen (2008-10-07):
+# Syria has now officially decided to end DST on 2008-11-01 this year,
+# according to the following article in the Syrian Arab News Agency (SANA).
+#
+# The article is in Arabic, and seems to tell that they will go back to
+# winter time on 2008-11-01 at 00:00 local daylight time (delaying/setting
+# clocks back 60 minutes).
+#
+# <a href="http://sana.sy/ara/2/2008/10/07/195459.htm">
+# http://sana.sy/ara/2/2008/10/07/195459.htm
+# </a>
+
+Rule Syria 2008 max - Apr Fri>=1 0:00 1:00 S
+Rule Syria 2008 max - Nov 1 0:00 0 -
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Damascus 2:25:12 - LMT 1920 # Dimashq
+ 2:00 Syria EE%sT
+
+# Tajikistan
+# From Shanks & Pottenger.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Dushanbe 4:35:12 - LMT 1924 May 2
+ 5:00 - DUST 1930 Jun 21 # Dushanbe Time
+ 6:00 RussiaAsia DUS%sT 1991 Mar 31 2:00s
+ 5:00 1:00 DUSST 1991 Sep 9 2:00s
+ 5:00 - TJT # Tajikistan Time
+
+# Thailand
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Bangkok 6:42:04 - LMT 1880
+ 6:42:04 - BMT 1920 Apr # Bangkok Mean Time
+ 7:00 - ICT
+
+# Turkmenistan
+# From Shanks & Pottenger.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Ashgabat 3:53:32 - LMT 1924 May 2 # or Ashkhabad
+ 4:00 - ASHT 1930 Jun 21 # Ashkhabad Time
+ 5:00 RussiaAsia ASH%sT 1991 Mar 31 2:00
+ 4:00 RussiaAsia ASH%sT 1991 Oct 27 # independence
+ 4:00 RussiaAsia TM%sT 1992 Jan 19 2:00
+ 5:00 - TMT
+
+# United Arab Emirates
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Dubai 3:41:12 - LMT 1920
+ 4:00 - GST
+
+# Uzbekistan
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Samarkand 4:27:12 - LMT 1924 May 2
+ 4:00 - SAMT 1930 Jun 21 # Samarkand Time
+ 5:00 - SAMT 1981 Apr 1
+ 5:00 1:00 SAMST 1981 Oct 1
+ 6:00 - TAST 1982 Apr 1 # Tashkent Time
+ 5:00 RussiaAsia SAM%sT 1991 Sep 1 # independence
+ 5:00 RussiaAsia UZ%sT 1992
+ 5:00 - UZT
+Zone Asia/Tashkent 4:37:12 - LMT 1924 May 2
+ 5:00 - TAST 1930 Jun 21 # Tashkent Time
+ 6:00 RussiaAsia TAS%sT 1991 Mar 31 2:00
+ 5:00 RussiaAsia TAS%sT 1991 Sep 1 # independence
+ 5:00 RussiaAsia UZ%sT 1992
+ 5:00 - UZT
+
+# Vietnam
+
+# From Arthur David Olson (2008-03-18):
+# The English-language name of Vietnam's most populous city is "Ho Chi Min City";
+# we use Ho_Chi_Minh below to avoid a name of more than 14 characters.
+
+# From Shanks & Pottenger:
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Ho_Chi_Minh 7:06:40 - LMT 1906 Jun 9
+ 7:06:20 - SMT 1911 Mar 11 0:01 # Saigon MT?
+ 7:00 - ICT 1912 May
+ 8:00 - ICT 1931 May
+ 7:00 - ICT
+
+# Yemen
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Asia/Aden 3:00:48 - LMT 1950
+ 3:00 - AST
diff --git a/tools/zoneinfo/tzdata2008h/australasia b/tools/zoneinfo/tzdata2008h/australasia
new file mode 100644
index 0000000..41608cd
--- /dev/null
+++ b/tools/zoneinfo/tzdata2008h/australasia
@@ -0,0 +1,1454 @@
+# @(#)australasia 8.9
+# <pre>
+
+# This file also includes Pacific islands.
+
+# Notes are at the end of this file
+
+###############################################################################
+
+# Australia
+
+# Please see the notes below for the controversy about "EST" versus "AEST" etc.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Aus 1917 only - Jan 1 0:01 1:00 -
+Rule Aus 1917 only - Mar 25 2:00 0 -
+Rule Aus 1942 only - Jan 1 2:00 1:00 -
+Rule Aus 1942 only - Mar 29 2:00 0 -
+Rule Aus 1942 only - Sep 27 2:00 1:00 -
+Rule Aus 1943 1944 - Mar lastSun 2:00 0 -
+Rule Aus 1943 only - Oct 3 2:00 1:00 -
+# Go with Whitman and the Australian National Standards Commission, which
+# says W Australia didn't use DST in 1943/1944. Ignore Whitman's claim that
+# 1944/1945 was just like 1943/1944.
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Northern Territory
+Zone Australia/Darwin 8:43:20 - LMT 1895 Feb
+ 9:00 - CST 1899 May
+ 9:30 Aus CST
+# Western Australia
+#
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule AW 1974 only - Oct lastSun 2:00s 1:00 -
+Rule AW 1975 only - Mar Sun>=1 2:00s 0 -
+Rule AW 1983 only - Oct lastSun 2:00s 1:00 -
+Rule AW 1984 only - Mar Sun>=1 2:00s 0 -
+Rule AW 1991 only - Nov 17 2:00s 1:00 -
+Rule AW 1992 only - Mar Sun>=1 2:00s 0 -
+Rule AW 2006 only - Dec 3 2:00s 1:00 -
+Rule AW 2007 2009 - Mar lastSun 2:00s 0 -
+Rule AW 2007 2008 - Oct lastSun 2:00s 1:00 -
+Zone Australia/Perth 7:43:24 - LMT 1895 Dec
+ 8:00 Aus WST 1943 Jul
+ 8:00 AW WST
+Zone Australia/Eucla 8:35:28 - LMT 1895 Dec
+ 8:45 Aus CWST 1943 Jul
+ 8:45 AW CWST
+
+# Queensland
+#
+# From Alex Livingston (1996-11-01):
+# I have heard or read more than once that some resort islands off the coast
+# of Queensland chose to keep observing daylight-saving time even after
+# Queensland ceased to.
+#
+# From Paul Eggert (1996-11-22):
+# IATA SSIM (1993-02/1994-09) say that the Holiday Islands (Hayman, Lindeman,
+# Hamilton) observed DST for two years after the rest of Queensland stopped.
+# Hamilton is the largest, but there is also a Hamilton in Victoria,
+# so use Lindeman.
+#
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule AQ 1971 only - Oct lastSun 2:00s 1:00 -
+Rule AQ 1972 only - Feb lastSun 2:00s 0 -
+Rule AQ 1989 1991 - Oct lastSun 2:00s 1:00 -
+Rule AQ 1990 1992 - Mar Sun>=1 2:00s 0 -
+Rule Holiday 1992 1993 - Oct lastSun 2:00s 1:00 -
+Rule Holiday 1993 1994 - Mar Sun>=1 2:00s 0 -
+Zone Australia/Brisbane 10:12:08 - LMT 1895
+ 10:00 Aus EST 1971
+ 10:00 AQ EST
+Zone Australia/Lindeman 9:55:56 - LMT 1895
+ 10:00 Aus EST 1971
+ 10:00 AQ EST 1992 Jul
+ 10:00 Holiday EST
+
+# South Australia
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule AS 1971 1985 - Oct lastSun 2:00s 1:00 -
+Rule AS 1986 only - Oct 19 2:00s 1:00 -
+Rule AS 1987 2007 - Oct lastSun 2:00s 1:00 -
+Rule AS 1972 only - Feb 27 2:00s 0 -
+Rule AS 1973 1985 - Mar Sun>=1 2:00s 0 -
+Rule AS 1986 1989 - Mar Sun>=15 2:00s 0 -
+Rule AS 1990 only - Mar Sun>=18 2:00s 0 -
+Rule AS 1991 only - Mar Sun>=1 2:00s 0 -
+Rule AS 1992 only - Mar Sun>=18 2:00s 0 -
+Rule AS 1993 only - Mar Sun>=1 2:00s 0 -
+Rule AS 1994 only - Mar Sun>=18 2:00s 0 -
+Rule AS 1995 2005 - Mar lastSun 2:00s 0 -
+Rule AS 2006 only - Apr Sun>=1 2:00s 0 -
+Rule AS 2007 only - Mar lastSun 2:00s 0 -
+Rule AS 2008 max - Apr Sun>=1 2:00s 0 -
+Rule AS 2008 max - Oct Sun>=1 2:00s 1:00 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Australia/Adelaide 9:14:20 - LMT 1895 Feb
+ 9:00 - CST 1899 May
+ 9:30 Aus CST 1971
+ 9:30 AS CST
+
+# Tasmania
+#
+# From Paul Eggert (2005-08-16):
+# <http://www.bom.gov.au/climate/averages/tables/dst_times.shtml>
+# says King Island didn't observe DST from WWII until late 1971.
+#
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule AT 1967 only - Oct Sun>=1 2:00s 1:00 -
+Rule AT 1968 only - Mar lastSun 2:00s 0 -
+Rule AT 1968 1985 - Oct lastSun 2:00s 1:00 -
+Rule AT 1969 1971 - Mar Sun>=8 2:00s 0 -
+Rule AT 1972 only - Feb lastSun 2:00s 0 -
+Rule AT 1973 1981 - Mar Sun>=1 2:00s 0 -
+Rule AT 1982 1983 - Mar lastSun 2:00s 0 -
+Rule AT 1984 1986 - Mar Sun>=1 2:00s 0 -
+Rule AT 1986 only - Oct Sun>=15 2:00s 1:00 -
+Rule AT 1987 1990 - Mar Sun>=15 2:00s 0 -
+Rule AT 1987 only - Oct Sun>=22 2:00s 1:00 -
+Rule AT 1988 1990 - Oct lastSun 2:00s 1:00 -
+Rule AT 1991 1999 - Oct Sun>=1 2:00s 1:00 -
+Rule AT 1991 2005 - Mar lastSun 2:00s 0 -
+Rule AT 2000 only - Aug lastSun 2:00s 1:00 -
+Rule AT 2001 max - Oct Sun>=1 2:00s 1:00 -
+Rule AT 2006 only - Apr Sun>=1 2:00s 0 -
+Rule AT 2007 only - Mar lastSun 2:00s 0 -
+Rule AT 2008 max - Apr Sun>=1 2:00s 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Australia/Hobart 9:49:16 - LMT 1895 Sep
+ 10:00 - EST 1916 Oct 1 2:00
+ 10:00 1:00 EST 1917 Feb
+ 10:00 Aus EST 1967
+ 10:00 AT EST
+Zone Australia/Currie 9:35:28 - LMT 1895 Sep
+ 10:00 - EST 1916 Oct 1 2:00
+ 10:00 1:00 EST 1917 Feb
+ 10:00 Aus EST 1971 Jul
+ 10:00 AT EST
+
+# Victoria
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule AV 1971 1985 - Oct lastSun 2:00s 1:00 -
+Rule AV 1972 only - Feb lastSun 2:00s 0 -
+Rule AV 1973 1985 - Mar Sun>=1 2:00s 0 -
+Rule AV 1986 1990 - Mar Sun>=15 2:00s 0 -
+Rule AV 1986 1987 - Oct Sun>=15 2:00s 1:00 -
+Rule AV 1988 1999 - Oct lastSun 2:00s 1:00 -
+Rule AV 1991 1994 - Mar Sun>=1 2:00s 0 -
+Rule AV 1995 2005 - Mar lastSun 2:00s 0 -
+Rule AV 2000 only - Aug lastSun 2:00s 1:00 -
+Rule AV 2001 2007 - Oct lastSun 2:00s 1:00 -
+Rule AV 2006 only - Apr Sun>=1 2:00s 0 -
+Rule AV 2007 only - Mar lastSun 2:00s 0 -
+Rule AV 2008 max - Apr Sun>=1 2:00s 0 -
+Rule AV 2008 max - Oct Sun>=1 2:00s 1:00 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Australia/Melbourne 9:39:52 - LMT 1895 Feb
+ 10:00 Aus EST 1971
+ 10:00 AV EST
+
+# New South Wales
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule AN 1971 1985 - Oct lastSun 2:00s 1:00 -
+Rule AN 1972 only - Feb 27 2:00s 0 -
+Rule AN 1973 1981 - Mar Sun>=1 2:00s 0 -
+Rule AN 1982 only - Apr Sun>=1 2:00s 0 -
+Rule AN 1983 1985 - Mar Sun>=1 2:00s 0 -
+Rule AN 1986 1989 - Mar Sun>=15 2:00s 0 -
+Rule AN 1986 only - Oct 19 2:00s 1:00 -
+Rule AN 1987 1999 - Oct lastSun 2:00s 1:00 -
+Rule AN 1990 1995 - Mar Sun>=1 2:00s 0 -
+Rule AN 1996 2005 - Mar lastSun 2:00s 0 -
+Rule AN 2000 only - Aug lastSun 2:00s 1:00 -
+Rule AN 2001 2007 - Oct lastSun 2:00s 1:00 -
+Rule AN 2006 only - Apr Sun>=1 2:00s 0 -
+Rule AN 2007 only - Mar lastSun 2:00s 0 -
+Rule AN 2008 max - Apr Sun>=1 2:00s 0 -
+Rule AN 2008 max - Oct Sun>=1 2:00s 1:00 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Australia/Sydney 10:04:52 - LMT 1895 Feb
+ 10:00 Aus EST 1971
+ 10:00 AN EST
+Zone Australia/Broken_Hill 9:25:48 - LMT 1895 Feb
+ 10:00 - EST 1896 Aug 23
+ 9:00 - CST 1899 May
+ 9:30 Aus CST 1971
+ 9:30 AN CST 2000
+ 9:30 AS CST
+
+# Lord Howe Island
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule LH 1981 1984 - Oct lastSun 2:00 1:00 -
+Rule LH 1982 1985 - Mar Sun>=1 2:00 0 -
+Rule LH 1985 only - Oct lastSun 2:00 0:30 -
+Rule LH 1986 1989 - Mar Sun>=15 2:00 0 -
+Rule LH 1986 only - Oct 19 2:00 0:30 -
+Rule LH 1987 1999 - Oct lastSun 2:00 0:30 -
+Rule LH 1990 1995 - Mar Sun>=1 2:00 0 -
+Rule LH 1996 2005 - Mar lastSun 2:00 0 -
+Rule LH 2000 only - Aug lastSun 2:00 0:30 -
+Rule LH 2001 2007 - Oct lastSun 2:00 0:30 -
+Rule LH 2006 only - Apr Sun>=1 2:00 0 -
+Rule LH 2007 only - Mar lastSun 2:00 0 -
+Rule LH 2008 max - Apr Sun>=1 2:00 0 -
+Rule LH 2008 max - Oct Sun>=1 2:00 0:30 -
+Zone Australia/Lord_Howe 10:36:20 - LMT 1895 Feb
+ 10:00 - EST 1981 Mar
+ 10:30 LH LHST
+
+# Australian miscellany
+#
+# Ashmore Is, Cartier
+# no indigenous inhabitants; only seasonal caretakers
+# no times are set
+#
+# Coral Sea Is
+# no indigenous inhabitants; only meteorologists
+# no times are set
+#
+# Macquarie
+# permanent occupation (scientific station) since 1948;
+# sealing and penguin oil station operated 1888/1917
+# like Australia/Hobart
+
+# Christmas
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Indian/Christmas 7:02:52 - LMT 1895 Feb
+ 7:00 - CXT # Christmas Island Time
+
+# Cook Is
+# From Shanks & Pottenger:
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Cook 1978 only - Nov 12 0:00 0:30 HS
+Rule Cook 1979 1991 - Mar Sun>=1 0:00 0 -
+Rule Cook 1979 1990 - Oct lastSun 0:00 0:30 HS
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Rarotonga -10:39:04 - LMT 1901 # Avarua
+ -10:30 - CKT 1978 Nov 12 # Cook Is Time
+ -10:00 Cook CK%sT
+
+# Cocos
+# These islands were ruled by the Ross family from about 1830 to 1978.
+# We don't know when standard time was introduced; for now, we guess 1900.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Indian/Cocos 6:27:40 - LMT 1900
+ 6:30 - CCT # Cocos Islands Time
+
+# Fiji
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Fiji 1998 1999 - Nov Sun>=1 2:00 1:00 S
+Rule Fiji 1999 2000 - Feb lastSun 3:00 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Fiji 11:53:40 - LMT 1915 Oct 26 # Suva
+ 12:00 Fiji FJ%sT # Fiji Time
+
+# French Polynesia
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Gambier -8:59:48 - LMT 1912 Oct # Rikitea
+ -9:00 - GAMT # Gambier Time
+Zone Pacific/Marquesas -9:18:00 - LMT 1912 Oct
+ -9:30 - MART # Marquesas Time
+Zone Pacific/Tahiti -9:58:16 - LMT 1912 Oct # Papeete
+ -10:00 - TAHT # Tahiti Time
+# Clipperton (near North America) is administered from French Polynesia;
+# it is uninhabited.
+
+# Guam
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Guam -14:21:00 - LMT 1844 Dec 31
+ 9:39:00 - LMT 1901 # Agana
+ 10:00 - GST 2000 Dec 23 # Guam
+ 10:00 - ChST # Chamorro Standard Time
+
+# Kiribati
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Tarawa 11:32:04 - LMT 1901 # Bairiki
+ 12:00 - GILT # Gilbert Is Time
+Zone Pacific/Enderbury -11:24:20 - LMT 1901
+ -12:00 - PHOT 1979 Oct # Phoenix Is Time
+ -11:00 - PHOT 1995
+ 13:00 - PHOT
+Zone Pacific/Kiritimati -10:29:20 - LMT 1901
+ -10:40 - LINT 1979 Oct # Line Is Time
+ -10:00 - LINT 1995
+ 14:00 - LINT
+
+# N Mariana Is
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Saipan -14:17:00 - LMT 1844 Dec 31
+ 9:43:00 - LMT 1901
+ 9:00 - MPT 1969 Oct # N Mariana Is Time
+ 10:00 - MPT 2000 Dec 23
+ 10:00 - ChST # Chamorro Standard Time
+
+# Marshall Is
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Majuro 11:24:48 - LMT 1901
+ 11:00 - MHT 1969 Oct # Marshall Islands Time
+ 12:00 - MHT
+Zone Pacific/Kwajalein 11:09:20 - LMT 1901
+ 11:00 - MHT 1969 Oct
+ -12:00 - KWAT 1993 Aug 20 # Kwajalein Time
+ 12:00 - MHT
+
+# Micronesia
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Truk 10:07:08 - LMT 1901
+ 10:00 - TRUT # Truk Time
+Zone Pacific/Ponape 10:32:52 - LMT 1901 # Kolonia
+ 11:00 - PONT # Ponape Time
+Zone Pacific/Kosrae 10:51:56 - LMT 1901
+ 11:00 - KOST 1969 Oct # Kosrae Time
+ 12:00 - KOST 1999
+ 11:00 - KOST
+
+# Nauru
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Nauru 11:07:40 - LMT 1921 Jan 15 # Uaobe
+ 11:30 - NRT 1942 Mar 15 # Nauru Time
+ 9:00 - JST 1944 Aug 15
+ 11:30 - NRT 1979 May
+ 12:00 - NRT
+
+# New Caledonia
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule NC 1977 1978 - Dec Sun>=1 0:00 1:00 S
+Rule NC 1978 1979 - Feb 27 0:00 0 -
+Rule NC 1996 only - Dec 1 2:00s 1:00 S
+# Shanks & Pottenger say the following was at 2:00; go with IATA.
+Rule NC 1997 only - Mar 2 2:00s 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Noumea 11:05:48 - LMT 1912 Jan 13
+ 11:00 NC NC%sT
+
+
+###############################################################################
+
+# New Zealand
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule NZ 1927 only - Nov 6 2:00 1:00 S
+Rule NZ 1928 only - Mar 4 2:00 0 M
+Rule NZ 1928 1933 - Oct Sun>=8 2:00 0:30 S
+Rule NZ 1929 1933 - Mar Sun>=15 2:00 0 M
+Rule NZ 1934 1940 - Apr lastSun 2:00 0 M
+Rule NZ 1934 1940 - Sep lastSun 2:00 0:30 S
+Rule NZ 1946 only - Jan 1 0:00 0 S
+# Since 1957 Chatham has been 45 minutes ahead of NZ, but there's no
+# convenient notation for this so we must duplicate the Rule lines.
+Rule NZ 1974 only - Nov Sun>=1 2:00s 1:00 D
+Rule Chatham 1974 only - Nov Sun>=1 2:45s 1:00 D
+Rule NZ 1975 only - Feb lastSun 2:00s 0 S
+Rule Chatham 1975 only - Feb lastSun 2:45s 0 S
+Rule NZ 1975 1988 - Oct lastSun 2:00s 1:00 D
+Rule Chatham 1975 1988 - Oct lastSun 2:45s 1:00 D
+Rule NZ 1976 1989 - Mar Sun>=1 2:00s 0 S
+Rule Chatham 1976 1989 - Mar Sun>=1 2:45s 0 S
+Rule NZ 1989 only - Oct Sun>=8 2:00s 1:00 D
+Rule Chatham 1989 only - Oct Sun>=8 2:45s 1:00 D
+Rule NZ 1990 2006 - Oct Sun>=1 2:00s 1:00 D
+Rule Chatham 1990 2006 - Oct Sun>=1 2:45s 1:00 D
+Rule NZ 1990 2007 - Mar Sun>=15 2:00s 0 S
+Rule Chatham 1990 2007 - Mar Sun>=15 2:45s 0 S
+Rule NZ 2007 max - Sep lastSun 2:00s 1:00 D
+Rule Chatham 2007 max - Sep lastSun 2:45s 1:00 D
+Rule NZ 2008 max - Apr Sun>=1 2:00s 0 S
+Rule Chatham 2008 max - Apr Sun>=1 2:45s 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Auckland 11:39:04 - LMT 1868 Nov 2
+ 11:30 NZ NZ%sT 1946 Jan 1
+ 12:00 NZ NZ%sT
+Zone Pacific/Chatham 12:13:48 - LMT 1957 Jan 1
+ 12:45 Chatham CHA%sT
+
+
+# Auckland Is
+# uninhabited; Maori and Moriori, colonial settlers, pastoralists, sealers,
+# and scientific personnel have wintered
+
+# Campbell I
+# minor whaling stations operated 1909/1914
+# scientific station operated 1941/1995;
+# previously whalers, sealers, pastoralists, and scientific personnel wintered
+# was probably like Pacific/Auckland
+
+###############################################################################
+
+
+# Niue
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Niue -11:19:40 - LMT 1901 # Alofi
+ -11:20 - NUT 1951 # Niue Time
+ -11:30 - NUT 1978 Oct 1
+ -11:00 - NUT
+
+# Norfolk
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Norfolk 11:11:52 - LMT 1901 # Kingston
+ 11:12 - NMT 1951 # Norfolk Mean Time
+ 11:30 - NFT # Norfolk Time
+
+# Palau (Belau)
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Palau 8:57:56 - LMT 1901 # Koror
+ 9:00 - PWT # Palau Time
+
+# Papua New Guinea
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Port_Moresby 9:48:40 - LMT 1880
+ 9:48:32 - PMMT 1895 # Port Moresby Mean Time
+ 10:00 - PGT # Papua New Guinea Time
+
+# Pitcairn
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Pitcairn -8:40:20 - LMT 1901 # Adamstown
+ -8:30 - PNT 1998 Apr 27 00:00
+ -8:00 - PST # Pitcairn Standard Time
+
+# American Samoa
+Zone Pacific/Pago_Pago 12:37:12 - LMT 1879 Jul 5
+ -11:22:48 - LMT 1911
+ -11:30 - SAMT 1950 # Samoa Time
+ -11:00 - NST 1967 Apr # N=Nome
+ -11:00 - BST 1983 Nov 30 # B=Bering
+ -11:00 - SST # S=Samoa
+
+# Samoa
+Zone Pacific/Apia 12:33:04 - LMT 1879 Jul 5
+ -11:26:56 - LMT 1911
+ -11:30 - SAMT 1950 # Samoa Time
+ -11:00 - WST # Samoa Time
+
+# Solomon Is
+# excludes Bougainville, for which see Papua New Guinea
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Guadalcanal 10:39:48 - LMT 1912 Oct # Honiara
+ 11:00 - SBT # Solomon Is Time
+
+# Tokelau Is
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Fakaofo -11:24:56 - LMT 1901
+ -10:00 - TKT # Tokelau Time
+
+# Tonga
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Tonga 1999 only - Oct 7 2:00s 1:00 S
+Rule Tonga 2000 only - Mar 19 2:00s 0 -
+Rule Tonga 2000 2001 - Nov Sun>=1 2:00 1:00 S
+Rule Tonga 2001 2002 - Jan lastSun 2:00 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Tongatapu 12:19:20 - LMT 1901
+ 12:20 - TOT 1941 # Tonga Time
+ 13:00 - TOT 1999
+ 13:00 Tonga TO%sT
+
+# Tuvalu
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Funafuti 11:56:52 - LMT 1901
+ 12:00 - TVT # Tuvalu Time
+
+
+# US minor outlying islands
+
+# Howland, Baker
+# Howland was mined for guano by American companies 1857-1878 and British
+# 1886-1891; Baker was similar but exact dates are not known.
+# Inhabited by civilians 1935-1942; U.S. military bases 1943-1944;
+# uninhabited thereafter.
+# Howland observed Hawaii Standard Time (UTC-10:30) in 1937;
+# see page 206 of Elgen M. Long and Marie K. Long,
+# Amelia Earhart: the Mystery Solved, Simon & Schuster (2000).
+# So most likely Howland and Baker observed Hawaii Time from 1935
+# until they were abandoned after the war.
+
+# Jarvis
+# Mined for guano by American companies 1857-1879 and British 1883?-1891?.
+# Inhabited by civilians 1935-1942; IGY scientific base 1957-1958;
+# uninhabited thereafter.
+# no information; was probably like Pacific/Kiritimati
+
+# Johnston
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Johnston -10:00 - HST
+
+# Kingman
+# uninhabited
+
+# Midway
+#
+# From Mark Brader (2005-01-23):
+# [Fallacies and Fantasies of Air Transport History, by R.E.G. Davies,
+# published 1994 by Paladwr Press, McLean, VA, USA; ISBN 0-9626483-5-3]
+# reproduced a Pan American Airways timeables from 1936, for their weekly
+# "Orient Express" flights between San Francisco and Manila, and connecting
+# flights to Chicago and the US East Coast. As it uses some time zone
+# designations that I've never seen before:....
+# Fri. 6:30A Lv. HONOLOLU (Pearl Harbor), H.I. H.L.T. Ar. 5:30P Sun.
+# " 3:00P Ar. MIDWAY ISLAND . . . . . . . . . M.L.T. Lv. 6:00A "
+#
+Zone Pacific/Midway -11:49:28 - LMT 1901
+ -11:00 - NST 1956 Jun 3
+ -11:00 1:00 NDT 1956 Sep 2
+ -11:00 - NST 1967 Apr # N=Nome
+ -11:00 - BST 1983 Nov 30 # B=Bering
+ -11:00 - SST # S=Samoa
+
+# Palmyra
+# uninhabited since World War II; was probably like Pacific/Kiritimati
+
+# Wake
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Wake 11:06:28 - LMT 1901
+ 12:00 - WAKT # Wake Time
+
+
+# Vanuatu
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Vanuatu 1983 only - Sep 25 0:00 1:00 S
+Rule Vanuatu 1984 1991 - Mar Sun>=23 0:00 0 -
+Rule Vanuatu 1984 only - Oct 23 0:00 1:00 S
+Rule Vanuatu 1985 1991 - Sep Sun>=23 0:00 1:00 S
+Rule Vanuatu 1992 1993 - Jan Sun>=23 0:00 0 -
+Rule Vanuatu 1992 only - Oct Sun>=23 0:00 1:00 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Efate 11:13:16 - LMT 1912 Jan 13 # Vila
+ 11:00 Vanuatu VU%sT # Vanuatu Time
+
+# Wallis and Futuna
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Pacific/Wallis 12:15:20 - LMT 1901
+ 12:00 - WFT # Wallis & Futuna Time
+
+###############################################################################
+
+# NOTES
+
+# This data is by no means authoritative; if you think you know better,
+# go ahead and edit the file (and please send any changes to
+# tz@elsie.nci.nih.gov for general use in the future).
+
+# From Paul Eggert (2006-03-22):
+# A good source for time zone historical data outside the U.S. is
+# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
+# San Diego: ACS Publications, Inc. (2003).
+#
+# Gwillim Law writes that a good source
+# for recent time zone data is the International Air Transport
+# Association's Standard Schedules Information Manual (IATA SSIM),
+# published semiannually. Law sent in several helpful summaries
+# of the IATA's data after 1990.
+#
+# Except where otherwise noted, Shanks & Pottenger is the source for
+# entries through 1990, and IATA SSIM is the source for entries afterwards.
+#
+# Another source occasionally used is Edward W. Whitman, World Time Differences,
+# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which
+# I found in the UCLA library.
+#
+# A reliable and entertaining source about time zones is
+# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
+#
+# I invented the abbreviations marked `*' in the following table;
+# the rest are from earlier versions of this file, or from other sources.
+# Corrections are welcome!
+# std dst
+# LMT Local Mean Time
+# 8:00 WST WST Western Australia
+# 8:45 CWST CWST Central Western Australia*
+# 9:00 JST Japan
+# 9:30 CST CST Central Australia
+# 10:00 EST EST Eastern Australia
+# 10:00 ChST Chamorro
+# 10:30 LHST LHST Lord Howe*
+# 11:30 NZMT NZST New Zealand through 1945
+# 12:00 NZST NZDT New Zealand 1946-present
+# 12:45 CHAST CHADT Chatham*
+# -11:00 SST Samoa
+# -10:00 HST Hawaii
+# - 8:00 PST Pitcairn*
+#
+# See the `northamerica' file for Hawaii.
+# See the `southamerica' file for Easter I and the Galapagos Is.
+
+###############################################################################
+
+# Australia
+
+# From Paul Eggert (2005-12-08):
+# <a href="http://www.bom.gov.au/climate/averages/tables/dst_times.shtml">
+# Implementation Dates of Daylight Saving Time within Australia
+# </a> summarizes daylight saving issues in Australia.
+
+# From Arthur David Olson (2005-12-12):
+# <a href="http://www.lawlink.nsw.gov.au/lawlink/Corporate/ll_agdinfo.nsf/pages/community_relations_daylight_saving">
+# Lawlink NSW:Daylight Saving in New South Wales
+# </a> covers New South Wales in particular.
+
+# From John Mackin (1991-03-06):
+# We in Australia have _never_ referred to DST as `daylight' time.
+# It is called `summer' time. Now by a happy coincidence, `summer'
+# and `standard' happen to start with the same letter; hence, the
+# abbreviation does _not_ change...
+# The legislation does not actually define abbreviations, at least
+# in this State, but the abbreviation is just commonly taken to be the
+# initials of the phrase, and the legislation here uniformly uses
+# the phrase `summer time' and does not use the phrase `daylight
+# time'.
+# Announcers on the Commonwealth radio network, the ABC (for Australian
+# Broadcasting Commission), use the phrases `Eastern Standard Time'
+# or `Eastern Summer Time'. (Note, though, that as I say in the
+# current australasia file, there is really no such thing.) Announcers
+# on its overseas service, Radio Australia, use the same phrases
+# prefixed by the word `Australian' when referring to local times;
+# time announcements on that service, naturally enough, are made in UTC.
+
+# From Arthur David Olson (1992-03-08):
+# Given the above, what's chosen for year-round use is:
+# CST for any place operating at a GMTOFF of 9:30
+# WST for any place operating at a GMTOFF of 8:00
+# EST for any place operating at a GMTOFF of 10:00
+
+# From Chuck Soper (2006-06-01):
+# I recently found this Australian government web page on time zones:
+# <http://www.australia.gov.au/about-australia-13time>
+# And this government web page lists time zone names and abbreviations:
+# <http://www.bom.gov.au/climate/averages/tables/daysavtm.shtml>
+
+# From Paul Eggert (2001-04-05), summarizing a long discussion about "EST"
+# versus "AEST" etc.:
+#
+# I see the following points of dispute:
+#
+# * How important are unique time zone abbreviations?
+#
+# Here I tend to agree with the point (most recently made by Chris
+# Newman) that unique abbreviations should not be essential for proper
+# operation of software. We have other instances of ambiguity
+# (e.g. "IST" denoting both "Israel Standard Time" and "Indian
+# Standard Time"), and they are not likely to go away any time soon.
+# In the old days, some software mistakenly relied on unique
+# abbreviations, but this is becoming less true with time, and I don't
+# think it's that important to cater to such software these days.
+#
+# On the other hand, there is another motivation for unambiguous
+# abbreviations: it cuts down on human confusion. This is
+# particularly true for Australia, where "EST" can mean one thing for
+# time T and a different thing for time T plus 1 second.
+#
+# * Does the relevant legislation indicate which abbreviations should be used?
+#
+# Here I tend to think that things are a mess, just as they are in
+# many other countries. We Americans are currently disagreeing about
+# which abbreviation to use for the newly legislated Chamorro Standard
+# Time, for example.
+#
+# Personally, I would prefer to use common practice; I would like to
+# refer to legislation only for examples of common practice, or as a
+# tiebreaker.
+#
+# * Do Australians more often use "Eastern Daylight Time" or "Eastern
+# Summer Time"? Do they typically prefix the time zone names with
+# the word "Australian"?
+#
+# My own impression is that both "Daylight Time" and "Summer Time" are
+# common and are widely understood, but that "Summer Time" is more
+# popular; and that the leading "A" is also common but is omitted more
+# often than not. I just used AltaVista advanced search and got the
+# following count of page hits:
+#
+# 1,103 "Eastern Summer Time" AND domain:au
+# 971 "Australian Eastern Summer Time" AND domain:au
+# 613 "Eastern Daylight Time" AND domain:au
+# 127 "Australian Eastern Daylight Time" AND domain:au
+#
+# Here "Summer" seems quite a bit more popular than "Daylight",
+# particularly when we know the time zone is Australian and not US,
+# say. The "Australian" prefix seems to be popular for Eastern Summer
+# Time, but unpopular for Eastern Daylight Time.
+#
+# For abbreviations, tools like AltaVista are less useful because of
+# ambiguity. Many hits are not really time zones, unfortunately, and
+# many hits denote US time zones and not Australian ones. But here
+# are the hit counts anyway:
+#
+# 161,304 "EST" and domain:au
+# 25,156 "EDT" and domain:au
+# 18,263 "AEST" and domain:au
+# 10,416 "AEDT" and domain:au
+#
+# 14,538 "CST" and domain:au
+# 5,728 "CDT" and domain:au
+# 176 "ACST" and domain:au
+# 29 "ACDT" and domain:au
+#
+# 7,539 "WST" and domain:au
+# 68 "AWST" and domain:au
+#
+# This data suggest that Australians tend to omit the "A" prefix in
+# practice. The situation for "ST" versus "DT" is less clear, given
+# the ambiguities involved.
+#
+# * How do Australians feel about the abbreviations in the tz database?
+#
+# If you just count Australians on this list, I count 2 in favor and 3
+# against. One of the "against" votes (David Keegel) counseled delay,
+# saying that both AEST/AEDT and EST/EST are widely used and
+# understood in Australia.
+
+# From Paul Eggert (1995-12-19):
+# Shanks & Pottenger report 2:00 for all autumn changes in Australia and NZ.
+# Mark Prior writes that his newspaper
+# reports that NSW's fall 1995 change will occur at 2:00,
+# but Robert Elz says it's been 3:00 in Victoria since 1970
+# and perhaps the newspaper's `2:00' is referring to standard time.
+# For now we'll continue to assume 2:00s for changes since 1960.
+
+# From Eric Ulevik (1998-01-05):
+#
+# Here are some URLs to Australian time legislation. These URLs are stable,
+# and should probably be included in the data file. There are probably more
+# relevant entries in this database.
+#
+# NSW (including LHI and Broken Hill):
+# <a href="http://www.austlii.edu.au/au/legis/nsw/consol_act/sta1987137/index.html">
+# Standard Time Act 1987 (updated 1995-04-04)
+# </a>
+# ACT
+# <a href="http://www.austlii.edu.au/au/legis/act/consol_act/stasta1972279/index.html">
+# Standard Time and Summer Time Act 1972
+# </a>
+# SA
+# <a href="http://www.austlii.edu.au/au/legis/sa/consol_act/sta1898137/index.html">
+# Standard Time Act, 1898
+# </a>
+
+# From David Grosz (2005-06-13):
+# It was announced last week that Daylight Saving would be extended by
+# one week next year to allow for the 2006 Commonwealth Games.
+# Daylight Saving is now to end for next year only on the first Sunday
+# in April instead of the last Sunday in March.
+#
+# From Gwillim Law (2005-06-14):
+# I did some Googling and found that all of those states (and territory) plan
+# to extend DST together in 2006.
+# ACT: http://www.cmd.act.gov.au/mediareleases/fileread.cfm?file=86.txt
+# New South Wales: http://www.thecouriermail.news.com.au/common/story_page/0,5936,15538869%255E1702,00.html
+# South Australia: http://www.news.com.au/story/0,10117,15555031-1246,00.html
+# Tasmania: http://www.media.tas.gov.au/release.php?id=14772
+# Victoria: I wasn't able to find anything separate, but the other articles
+# allude to it.
+# But not Queensland
+# http://www.news.com.au/story/0,10117,15564030-1248,00.html.
+
+# Northern Territory
+
+# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
+# # The NORTHERN TERRITORY.. [ Courtesy N.T. Dept of the Chief Minister ]
+# # [ Nov 1990 ]
+# # N.T. have never utilised any DST due to sub-tropical/tropical location.
+# ...
+# Zone Australia/North 9:30 - CST
+
+# From Bradley White (1991-03-04):
+# A recent excerpt from an Australian newspaper...
+# the Northern Territory do[es] not have daylight saving.
+
+# Western Australia
+
+# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
+# # The state of WESTERN AUSTRALIA.. [ Courtesy W.A. dept Premier+Cabinet ]
+# # [ Nov 1990 ]
+# # W.A. suffers from a great deal of public and political opposition to
+# # DST in principle. A bill is brought before parliament in most years, but
+# # usually defeated either in the upper house, or in party caucus
+# # before reaching parliament.
+# ...
+# Zone Australia/West 8:00 AW %sST
+# ...
+# Rule AW 1974 only - Oct lastSun 2:00 1:00 D
+# Rule AW 1975 only - Mar Sun>=1 3:00 0 W
+# Rule AW 1983 only - Oct lastSun 2:00 1:00 D
+# Rule AW 1984 only - Mar Sun>=1 3:00 0 W
+
+# From Bradley White (1991-03-04):
+# A recent excerpt from an Australian newspaper...
+# Western Australia...do[es] not have daylight saving.
+
+# From John D. Newman via Bradley White (1991-11-02):
+# Western Australia is still on "winter time". Some DH in Sydney
+# rang me at home a few days ago at 6.00am. (He had just arrived at
+# work at 9.00am.)
+# W.A. is switching to Summer Time on Nov 17th just to confuse
+# everybody again.
+
+# From Arthur David Olson (1992-03-08):
+# The 1992 ending date used in the rules is a best guess;
+# it matches what was used in the past.
+
+# <a href="http://www.bom.gov.au/faq/faqgen.htm">
+# The Australian Bureau of Meteorology FAQ
+# </a> (1999-09-27) writes that Giles Meteorological Station uses
+# South Australian time even though it's located in Western Australia.
+
+# Queensland
+# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
+# # The state of QUEENSLAND.. [ Courtesy Qld. Dept Premier Econ&Trade Devel ]
+# # [ Dec 1990 ]
+# ...
+# Zone Australia/Queensland 10:00 AQ %sST
+# ...
+# Rule AQ 1971 only - Oct lastSun 2:00 1:00 D
+# Rule AQ 1972 only - Feb lastSun 3:00 0 E
+# Rule AQ 1989 max - Oct lastSun 2:00 1:00 D
+# Rule AQ 1990 max - Mar Sun>=1 3:00 0 E
+
+# From Bradley White (1989-12-24):
+# "Australia/Queensland" now observes daylight time (i.e. from
+# October 1989).
+
+# From Bradley White (1991-03-04):
+# A recent excerpt from an Australian newspaper...
+# ...Queensland...[has] agreed to end daylight saving
+# at 3am tomorrow (March 3)...
+
+# From John Mackin (1991-03-06):
+# I can certainly confirm for my part that Daylight Saving in NSW did in fact
+# end on Sunday, 3 March. I don't know at what hour, though. (It surprised
+# me.)
+
+# From Bradley White (1992-03-08):
+# ...there was recently a referendum in Queensland which resulted
+# in the experimental daylight saving system being abandoned. So, ...
+# ...
+# Rule QLD 1989 1991 - Oct lastSun 2:00 1:00 D
+# Rule QLD 1990 1992 - Mar Sun>=1 3:00 0 S
+# ...
+
+# From Arthur David Olson (1992-03-08):
+# The chosen rules the union of the 1971/1972 change and the 1989-1992 changes.
+
+# From Christopher Hunt (2006-11-21), after an advance warning
+# from Jesper Norgaard Welen (2006-11-01):
+# WA are trialing DST for three years.
+# <http://www.parliament.wa.gov.au/parliament/bills.nsf/9A1B183144403DA54825721200088DF1/$File/Bill175-1B.pdf>
+
+# From Rives McDow (2002-04-09):
+# The most interesting region I have found consists of three towns on the
+# southern coast.... South Australia observes daylight saving time; Western
+# Australia does not. The two states are one and a half hours apart. The
+# residents decided to forget about this nonsense of changing the clock so
+# much and set the local time 20 hours and 45 minutes from the
+# international date line, or right in the middle of the time of South
+# Australia and Western Australia....
+#
+# From Paul Eggert (2002-04-09):
+# This is confirmed by the section entitled
+# "What's the deal with time zones???" in
+# <http://www.earthsci.unimelb.edu.au/~awatkins/null.html>.
+#
+# From Alex Livingston (2006-12-07):
+# ... it was just on four years ago that I drove along the Eyre Highway,
+# which passes through eastern Western Australia close to the southern
+# coast of the continent.
+#
+# I paid particular attention to the time kept there. There can be no
+# dispute that UTC+08:45 was considered "the time" from the border
+# village just inside the border with South Australia to as far west
+# as just east of Caiguna. There can also be no dispute that Eucla is
+# the largest population centre in this zone....
+#
+# Now that Western Australia is observing daylight saving, the
+# question arose whether this part of the state would follow suit. I
+# just called the border village and confirmed that indeed they have,
+# meaning that they are now observing UTC+09:45.
+#
+# (2006-12-09):
+# I personally doubt that either experimentation with daylight saving
+# in WA or its introduction in SA had anything to do with the genesis
+# of this time zone. My hunch is that it's been around since well
+# before 1975. I remember seeing it noted on road maps decades ago.
+
+# From Paul Eggert (2006-12-15):
+# For lack of better info, assume the tradition dates back to the
+# introduction of standard time in 1895.
+
+
+# southeast Australia
+#
+# From Paul Eggert (2007-07-23):
+# Starting autumn 2008 Victoria, NSW, South Australia, Tasmania and the ACT
+# end DST the first Sunday in April and start DST the first Sunday in October.
+# http://www.theage.com.au/news/national/daylight-savings-to-span-six-months/2007/06/27/1182623966703.html
+
+
+# South Australia
+
+# From Bradley White (1991-03-04):
+# A recent excerpt from an Australian newspaper...
+# ...South Australia...[has] agreed to end daylight saving
+# at 3am tomorrow (March 3)...
+
+# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
+# # The state of SOUTH AUSTRALIA....[ Courtesy of S.A. Dept of Labour ]
+# # [ Nov 1990 ]
+# ...
+# Zone Australia/South 9:30 AS %sST
+# ...
+# Rule AS 1971 max - Oct lastSun 2:00 1:00 D
+# Rule AS 1972 1985 - Mar Sun>=1 3:00 0 C
+# Rule AS 1986 1990 - Mar Sun>=15 3:00 0 C
+# Rule AS 1991 max - Mar Sun>=1 3:00 0 C
+
+# From Bradley White (1992-03-11):
+# Recent correspondence with a friend in Adelaide
+# contained the following exchange: "Due to the Adelaide Festival,
+# South Australia delays setting back our clocks for a few weeks."
+
+# From Robert Elz (1992-03-13):
+# I heard that apparently (or at least, it appears that)
+# South Aus will have an extra 3 weeks daylight saving every even
+# numbered year (from 1990). That's when the Adelaide Festival
+# is on...
+
+# From Robert Elz (1992-03-16, 00:57:07 +1000):
+# DST didn't end in Adelaide today (yesterday)....
+# But whether it's "4th Sunday" or "2nd last Sunday" I have no idea whatever...
+# (it's just as likely to be "the Sunday we pick for this year"...).
+
+# From Bradley White (1994-04-11):
+# If Sun, 15 March, 1992 was at +1030 as kre asserts, but yet Sun, 20 March,
+# 1994 was at +0930 as John Connolly's customer seems to assert, then I can
+# only conclude that the actual rule is more complicated....
+
+# From John Warburton (1994-10-07):
+# The new Daylight Savings dates for South Australia ...
+# was gazetted in the Government Hansard on Sep 26 1994....
+# start on last Sunday in October and end in last sunday in March.
+
+# From Paul Eggert (2007-07-23):
+# See "southeast Australia" above for 2008 and later.
+
+# Tasmania
+
+# The rules for 1967 through 1991 were reported by George Shepherd
+# via Simon Woodhead via Robert Elz (1991-03-06):
+# # The state of TASMANIA.. [Courtesy Tasmanian Dept of Premier + Cabinet ]
+# # [ Nov 1990 ]
+
+# From Bill Hart via Guy Harris (1991-10-10):
+# Oh yes, the new daylight savings rules are uniquely tasmanian, we have
+# 6 weeks a year now when we are out of sync with the rest of Australia
+# (but nothing new about that).
+
+# From Alex Livingston (1999-10-04):
+# I heard on the ABC (Australian Broadcasting Corporation) radio news on the
+# (long) weekend that Tasmania, which usually goes its own way in this regard,
+# has decided to join with most of NSW, the ACT, and most of Victoria
+# (Australia) and start daylight saving on the last Sunday in August in 2000
+# instead of the first Sunday in October.
+
+# Sim Alam (2000-07-03) reported a legal citation for the 2000/2001 rules:
+# http://www.thelaw.tas.gov.au/fragview/42++1968+GS3A@EN+2000070300
+
+# From Paul Eggert (2007-07-23):
+# See "southeast Australia" above for 2008 and later.
+
+# Victoria
+
+# The rules for 1971 through 1991 were reported by George Shepherd
+# via Simon Woodhead via Robert Elz (1991-03-06):
+# # The state of VICTORIA.. [ Courtesy of Vic. Dept of Premier + Cabinet ]
+# # [ Nov 1990 ]
+
+# From Scott Harrington (2001-08-29):
+# On KQED's "City Arts and Lectures" program last night I heard an
+# interesting story about daylight savings time. Dr. John Heilbron was
+# discussing his book "The Sun in the Church: Cathedrals as Solar
+# Observatories"[1], and in particular the Shrine of Remembrance[2] located
+# in Melbourne, Australia.
+#
+# Apparently the shrine's main purpose is a beam of sunlight which
+# illuminates a special spot on the floor at the 11th hour of the 11th day
+# of the 11th month (Remembrance Day) every year in memory of Australia's
+# fallen WWI soldiers. And if you go there on Nov. 11, at 11am local time,
+# you will indeed see the sunbeam illuminate the special spot at the
+# expected time.
+#
+# However, that is only because of some special mirror contraption that had
+# to be employed, since due to daylight savings time, the true solar time of
+# the remembrance moment occurs one hour later (or earlier?). Perhaps
+# someone with more information on this jury-rig can tell us more.
+#
+# [1] http://www.hup.harvard.edu/catalog/HEISUN.html
+# [2] http://www.shrine.org.au
+
+# From Paul Eggert (2007-07-23):
+# See "southeast Australia" above for 2008 and later.
+
+# New South Wales
+
+# From Arthur David Olson:
+# New South Wales and subjurisdictions have their own ideas of a fun time.
+# Based on law library research by John Mackin,
+# who notes:
+# In Australia, time is not legislated federally, but rather by the
+# individual states. Thus, while such terms as ``Eastern Standard Time''
+# [I mean, of course, Australian EST, not any other kind] are in common
+# use, _they have NO REAL MEANING_, as they are not defined in the
+# legislation. This is very important to understand.
+# I have researched New South Wales time only...
+
+# From Eric Ulevik (1999-05-26):
+# DST will start in NSW on the last Sunday of August, rather than the usual
+# October in 2000. [See: Matthew Moore,
+# <a href="http://www.smh.com.au/news/9905/26/pageone/pageone4.html">
+# Two months more daylight saving
+# </a>
+# Sydney Morning Herald (1999-05-26).]
+
+# From Paul Eggert (1999-09-27):
+# See the following official NSW source:
+# <a href="http://dir.gis.nsw.gov.au/cgi-bin/genobject/document/other/daylightsaving/tigGmZ">
+# Daylight Saving in New South Wales.
+# </a>
+#
+# Narrabri Shire (NSW) council has announced it will ignore the extension of
+# daylight saving next year. See:
+# <a href="http://abc.net.au/news/regionals/neweng/monthly/regeng-22jul1999-1.htm">
+# Narrabri Council to ignore daylight saving
+# </a> (1999-07-22). For now, we'll wait to see if this really happens.
+#
+# Victoria will following NSW. See:
+# <a href="http://abc.net.au/local/news/olympics/1999/07/item19990728112314_1.htm">
+# Vic to extend daylight saving
+# </a> (1999-07-28).
+#
+# However, South Australia rejected the DST request. See:
+# <a href="http://abc.net.au/news/olympics/1999/07/item19990719151754_1.htm">
+# South Australia rejects Olympics daylight savings request
+# </a> (1999-07-19).
+#
+# Queensland also will not observe DST for the Olympics. See:
+# <a href="http://abc.net.au/news/olympics/1999/06/item19990601114608_1.htm">
+# Qld says no to daylight savings for Olympics
+# </a> (1999-06-01), which quotes Queensland Premier Peter Beattie as saying
+# ``Look you've got to remember in my family when this came up last time
+# I voted for it, my wife voted against it and she said to me it's all very
+# well for you, you don't have to worry about getting the children out of
+# bed, getting them to school, getting them to sleep at night.
+# I've been through all this argument domestically...my wife rules.''
+#
+# Broken Hill will stick with South Australian time in 2000. See:
+# <a href="http://abc.net.au/news/regionals/brokenh/monthly/regbrok-21jul1999-6.htm">
+# Broken Hill to be behind the times
+# </a> (1999-07-21).
+
+# IATA SSIM (1998-09) says that the spring 2000 change for Australian
+# Capital Territory, New South Wales except Lord Howe Island and Broken
+# Hill, and Victoria will be August 27, presumably due to the Sydney Olympics.
+
+# From Eric Ulevik, referring to Sydney's Sun Herald (2000-08-13), page 29:
+# The Queensland Premier Peter Beattie is encouraging northern NSW
+# towns to use Queensland time.
+
+# From Paul Eggert (2007-07-23):
+# See "southeast Australia" above for 2008 and later.
+
+# Yancowinna
+
+# From John Mackin (1989-01-04):
+# `Broken Hill' means the County of Yancowinna.
+
+# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
+# # YANCOWINNA.. [ Confirmation courtesy of Broken Hill Postmaster ]
+# # [ Dec 1990 ]
+# ...
+# # Yancowinna uses Central Standard Time, despite [its] location on the
+# # New South Wales side of the S.A. border. Most business and social dealings
+# # are with CST zones, therefore CST is legislated by local government
+# # although the switch to Summer Time occurs in line with N.S.W. There have
+# # been years when this did not apply, but the historical data is not
+# # presently available.
+# Zone Australia/Yancowinna 9:30 AY %sST
+# ...
+# Rule AY 1971 1985 - Oct lastSun 2:00 1:00 D
+# Rule AY 1972 only - Feb lastSun 3:00 0 C
+# [followed by other Rules]
+
+# Lord Howe Island
+
+# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
+# LHI... [ Courtesy of Pauline Van Winsen ]
+# [ Dec 1990 ]
+# Lord Howe Island is located off the New South Wales coast, and is half an
+# hour ahead of NSW time.
+
+# From James Lonergan, Secretary, Lord Howe Island Board (2000-01-27):
+# Lord Howe Island summer time in 2000/2001 will commence on the same
+# date as the rest of NSW (i.e. 2000-08-27). For your information the
+# Lord Howe Island Board (controlling authority for the Island) is
+# seeking the community's views on various options for summer time
+# arrangements on the Island, e.g. advance clocks by 1 full hour
+# instead of only 30 minutes. Dependant on the wishes of residents
+# the Board may approach the NSW government to change the existing
+# arrangements. The starting date for summer time on the Island will
+# however always coincide with the rest of NSW.
+
+# From James Lonergan, Secretary, Lord Howe Island Board (2000-10-25):
+# Lord Howe Island advances clocks by 30 minutes during DST in NSW and retards
+# clocks by 30 minutes when DST finishes. Since DST was most recently
+# introduced in NSW, the "changeover" time on the Island has been 02:00 as
+# shown on clocks on LHI. I guess this means that for 30 minutes at the start
+# of DST, LHI is actually 1 hour ahead of the rest of NSW.
+
+# From Paul Eggert (2006-03-22):
+# For Lord Howe dates we use Shanks & Pottenger through 1989, and
+# Lonergan thereafter. For times we use Lonergan.
+
+# From Paul Eggert (2007-07-23):
+# See "southeast Australia" above for 2008 and later.
+
+###############################################################################
+
+# New Zealand
+
+# From Mark Davies (1990-10-03):
+# the 1989/90 year was a trial of an extended "daylight saving" period.
+# This trial was deemed successful and the extended period adopted for
+# subsequent years (with the addition of a further week at the start).
+# source -- phone call to Ministry of Internal Affairs Head Office.
+
+# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
+# # The Country of New Zealand (Australia's east island -) Gee they hate that!
+# # or is Australia the west island of N.Z.
+# # [ courtesy of Geoff Tribble.. Auckland N.Z. ]
+# # [ Nov 1990 ]
+# ...
+# Rule NZ 1974 1988 - Oct lastSun 2:00 1:00 D
+# Rule NZ 1989 max - Oct Sun>=1 2:00 1:00 D
+# Rule NZ 1975 1989 - Mar Sun>=1 3:00 0 S
+# Rule NZ 1990 max - Mar lastSun 3:00 0 S
+# ...
+# Zone NZ 12:00 NZ NZ%sT # New Zealand
+# Zone NZ-CHAT 12:45 - NZ-CHAT # Chatham Island
+
+# From Arthur David Olson (1992-03-08):
+# The chosen rules use the Davies October 8 values for the start of DST in 1989
+# rather than the October 1 value.
+
+# From Paul Eggert (1995-12-19);
+# Shank & Pottenger report 2:00 for all autumn changes in Australia and NZ.
+# Robert Uzgalis writes that the New Zealand Daylight
+# Savings Time Order in Council dated 1990-06-18 specifies 2:00 standard
+# time on both the first Sunday in October and the third Sunday in March.
+# As with Australia, we'll assume the tradition is 2:00s, not 2:00.
+#
+# From Paul Eggert (2006-03-22):
+# The Department of Internal Affairs (DIA) maintains a brief history,
+# as does Carol Squires; see tz-link.htm for the full references.
+# Use these sources in preference to Shanks & Pottenger.
+#
+# For Chatham, IATA SSIM (1991/1999) gives the NZ rules but with
+# transitions at 2:45 local standard time; this confirms that Chatham
+# is always exactly 45 minutes ahead of Auckland.
+
+# From Colin Sharples (2007-04-30):
+# DST will now start on the last Sunday in September, and end on the
+# first Sunday in April. The changes take effect this year, meaning
+# that DST will begin on 2007-09-30 2008-04-06.
+# http://www.dia.govt.nz/diawebsite.nsf/wpg_URL/Services-Daylight-Saving-Daylight-saving-to-be-extended
+
+###############################################################################
+
+
+# Fiji
+
+# Howse writes (p 153) that in 1879 the British governor of Fiji
+# enacted an ordinance standardizing the islands on Antipodean Time
+# instead of the American system (which was one day behind).
+
+# From Rives McDow (1998-10-08):
+# Fiji will introduce DST effective 0200 local time, 1998-11-01
+# until 0300 local time 1999-02-28. Each year the DST period will
+# be from the first Sunday in November until the last Sunday in February.
+
+# From Paul Eggert (2000-01-08):
+# IATA SSIM (1999-09) says DST ends 0100 local time. Go with McDow.
+
+# From the BBC World Service (1998-10-31 11:32 UTC):
+# The Fijiian government says the main reasons for the time change is to
+# improve productivity and reduce road accidents. But correspondents say it
+# also hopes the move will boost Fiji's ability to compete with other pacific
+# islands in the effort to attract tourists to witness the dawning of the new
+# millenium.
+
+# http://www.fiji.gov.fj/press/2000_09/2000_09_13-05.shtml (2000-09-13)
+# reports that Fiji has discontinued DST.
+
+# Johnston
+
+# Johnston data is from usno1995.
+
+
+# Kiribati
+
+# From Paul Eggert (1996-01-22):
+# Today's _Wall Street Journal_ (page 1) reports that Kiribati
+# ``declared it the same day throught the country as of Jan. 1, 1995''
+# as part of the competition to be first into the 21st century.
+
+
+# Kwajalein
+
+# In comp.risks 14.87 (26 August 1993), Peter Neumann writes:
+# I wonder what happened in Kwajalein, where there was NO Friday,
+# 1993-08-20. Thursday night at midnight Kwajalein switched sides with
+# respect to the International Date Line, to rejoin its fellow islands,
+# going from 11:59 p.m. Thursday to 12:00 m. Saturday in a blink.
+
+
+# N Mariana Is, Guam
+
+# Howse writes (p 153) ``The Spaniards, on the other hand, reached the
+# Philippines and the Ladrones from America,'' and implies that the Ladrones
+# (now called the Marianas) kept American date for quite some time.
+# For now, we assume the Ladrones switched at the same time as the Philippines;
+# see Asia/Manila.
+
+# US Public Law 106-564 (2000-12-23) made UTC+10 the official standard time,
+# under the name "Chamorro Standard Time". There is no official abbreviation,
+# but Congressman Robert A. Underwood, author of the bill that became law,
+# wrote in a press release (2000-12-27) that he will seek the use of "ChST".
+
+
+# Micronesia
+
+# Alan Eugene Davis writes (1996-03-16),
+# ``I am certain, having lived there for the past decade, that "Truk"
+# (now properly known as Chuuk) ... is in the time zone GMT+10.''
+#
+# Shanks & Pottenger write that Truk switched from UTC+10 to UTC+11
+# on 1978-10-01; ignore this for now.
+
+# From Paul Eggert (1999-10-29):
+# The Federated States of Micronesia Visitors Board writes in
+# <a href="http://www.fsmgov.org/info/clocks.html">
+# The Federated States of Micronesia - Visitor Information
+# </a> (1999-01-26)
+# that Truk and Yap are UTC+10, and Ponape and Kosrae are UTC+11.
+# We don't know when Kosrae switched from UTC+12; assume January 1 for now.
+
+
+# Midway
+
+# From Charles T O'Connor, KMTH DJ (1956),
+# quoted in the KTMH section of the Radio Heritage Collection
+# <http://radiodx.com/spdxr/KMTH.htm> (2002-12-31):
+# For the past two months we've been on what is known as Daylight
+# Saving Time. This time has put us on air at 5am in the morning,
+# your time down there in New Zealand. Starting September 2, 1956
+# we'll again go back to Standard Time. This'll mean that we'll go to
+# air at 6am your time.
+#
+# From Paul Eggert (2003-03-23):
+# We don't know the date of that quote, but we'll guess they
+# started DST on June 3. Possibly DST was observed other years
+# in Midway, but we have no record of it.
+
+
+# Pitcairn
+
+# From Rives McDow (1999-11-08):
+# A Proclamation was signed by the Governor of Pitcairn on the 27th March 1998
+# with regard to Pitcairn Standard Time. The Proclamation is as follows.
+#
+# The local time for general purposes in the Islands shall be
+# Co-ordinated Universal time minus 8 hours and shall be known
+# as Pitcairn Standard Time.
+#
+# ... I have also seen Pitcairn listed as UTC minus 9 hours in several
+# references, and can only assume that this was an error in interpretation
+# somehow in light of this proclamation.
+
+# From Rives McDow (1999-11-09):
+# The Proclamation regarding Pitcairn time came into effect on 27 April 1998
+# ... at midnight.
+
+# From Howie Phelps (1999-11-10), who talked to a Pitcairner via shortwave:
+# Betty Christian told me yesterday that their local time is the same as
+# Pacific Standard Time. They used to be 1/2 hour different from us here in
+# Sacramento but it was changed a couple of years ago.
+
+
+# Samoa
+
+# Howse writes (p 153, citing p 10 of the 1883-11-18 New York Herald)
+# that in 1879 the King of Samoa decided to change
+# ``the date in his kingdom from the Antipodean to the American system,
+# ordaining -- by a masterpiece of diplomatic flattery -- that
+# the Fourth of July should be celebrated twice in that year.''
+
+
+# Tonga
+
+# From Paul Eggert (1996-01-22):
+# Today's _Wall Street Journal_ (p 1) reports that ``Tonga has been plotting
+# to sneak ahead of [New Zealanders] by introducing daylight-saving time.''
+# Since Kiribati has moved the Date Line it's not clear what Tonga will do.
+
+# Don Mundell writes in the 1997-02-20 Tonga Chronicle
+# <a href="http://www.tongatapu.net.to/tonga/homeland/timebegins.htm">
+# How Tonga became `The Land where Time Begins'
+# </a>:
+
+# Until 1941 Tonga maintained a standard time 50 minutes ahead of NZST
+# 12 hours and 20 minutes ahead of GMT. When New Zealand adjusted its
+# standard time in 1940s, Tonga had the choice of subtracting from its
+# local time to come on the same standard time as New Zealand or of
+# advancing its time to maintain the differential of 13 degrees
+# (approximately 50 minutes ahead of New Zealand time).
+#
+# Because His Majesty King Taufa'ahau Tupou IV, then Crown Prince
+# Tungi, preferred to ensure Tonga's title as the land where time
+# begins, the Legislative Assembly approved the latter change.
+#
+# But some of the older, more conservative members from the outer
+# islands objected. "If at midnight on Dec. 31, we move ahead 40
+# minutes, as your Royal Highness wishes, what becomes of the 40
+# minutes we have lost?"
+#
+# The Crown Prince, presented an unanswerable argument: "Remember that
+# on the World Day of Prayer, you would be the first people on Earth
+# to say your prayers in the morning."
+
+# From Paul Eggert (2006-03-22):
+# Shanks & Pottenger say the transition was on 1968-10-01; go with Mundell.
+
+# From Eric Ulevik (1999-05-03):
+# Tonga's director of tourism, who is also secretary of the National Millenium
+# Committee, has a plan to get Tonga back in front.
+# He has proposed a one-off move to tropical daylight saving for Tonga from
+# October to March, which has won approval in principle from the Tongan
+# Government.
+
+# From Steffen Thorsen (1999-09-09):
+# * Tonga will introduce DST in November
+#
+# I was given this link by John Letts:
+# <a href="http://news.bbc.co.uk/hi/english/world/asia-pacific/newsid_424000/424764.stm">
+# http://news.bbc.co.uk/hi/english/world/asia-pacific/newsid_424000/424764.stm
+# </a>
+#
+# I have not been able to find exact dates for the transition in November
+# yet. By reading this article it seems like Fiji will be 14 hours ahead
+# of UTC as well, but as far as I know Fiji will only be 13 hours ahead
+# (12 + 1 hour DST).
+
+# From Arthur David Olson (1999-09-20):
+# According to <a href="http://www.tongaonline.com/news/sept1799.html">
+# http://www.tongaonline.com/news/sept1799.html
+# </a>:
+# "Daylight Savings Time will take effect on Oct. 2 through April 15, 2000
+# and annually thereafter from the first Saturday in October through the
+# third Saturday of April. Under the system approved by Privy Council on
+# Sept. 10, clocks must be turned ahead one hour on the opening day and
+# set back an hour on the closing date."
+# Alas, no indication of the time of day.
+
+# From Rives McDow (1999-10-06):
+# Tonga started its Daylight Saving on Saturday morning October 2nd at 0200am.
+# Daylight Saving ends on April 16 at 0300am which is Sunday morning.
+
+# From Steffen Thorsen (2000-10-31):
+# Back in March I found a notice on the website http://www.tongaonline.com
+# that Tonga changed back to standard time one month early, on March 19
+# instead of the original reported date April 16. Unfortunately, the article
+# is no longer available on the site, and I did not make a copy of the
+# text, and I have forgotten to report it here.
+# (Original URL was: http://www.tongaonline.com/news/march162000.htm )
+
+# From Rives McDow (2000-12-01):
+# Tonga is observing DST as of 2000-11-04 and will stop on 2001-01-27.
+
+# From Sione Moala-Mafi (2001-09-20) via Rives McDow:
+# At 2:00am on the first Sunday of November, the standard time in the Kingdom
+# shall be moved forward by one hour to 3:00am. At 2:00am on the last Sunday
+# of January the standard time in the Kingdom shall be moved backward by one
+# hour to 1:00am.
+
+# From Pulu 'Anau (2002-11-05):
+# The law was for 3 years, supposedly to get renewed. It wasn't.
+
+
+# Wake
+
+# From Vernice Anderson, Personal Secretary to Philip Jessup,
+# US Ambassador At Large (oral history interview, 1971-02-02):
+#
+# Saturday, the 14th [of October, 1950] -- ... The time was all the
+# more confusing at that point, because we had crossed the
+# International Date Line, thus getting two Sundays. Furthermore, we
+# discovered that Wake Island had two hours of daylight saving time
+# making calculation of time in Washington difficult if not almost
+# impossible.
+#
+# http://www.trumanlibrary.org/wake/meeting.htm
+
+# From Paul Eggert (2003-03-23):
+# We have no other report of DST in Wake Island, so omit this info for now.
+
+###############################################################################
+
+# The International Date Line
+
+# From Gwillim Law (2000-01-03):
+#
+# The International Date Line is not defined by any international standard,
+# convention, or treaty. Mapmakers are free to draw it as they please.
+# Reputable mapmakers will simply ensure that every point of land appears on
+# the correct side of the IDL, according to the date legally observed there.
+#
+# When Kiribati adopted a uniform date in 1995, thereby moving the Phoenix and
+# Line Islands to the west side of the IDL (or, if you prefer, moving the IDL
+# to the east side of the Phoenix and Line Islands), I suppose that most
+# mapmakers redrew the IDL following the boundary of Kiribati. Even that line
+# has a rather arbitrary nature. The straight-line boundaries between Pacific
+# island nations that are shown on many maps are based on an international
+# convention, but are not legally binding national borders.... The date is
+# governed by the IDL; therefore, even on the high seas, there may be some
+# places as late as fourteen hours later than UTC. And, since the IDL is not
+# an international standard, there are some places on the high seas where the
+# correct date is ambiguous.
+
+# From Wikipedia <http://en.wikipedia.org/wiki/Time_zone> (2005-08-31):
+# Before 1920, all ships kept local apparent time on the high seas by setting
+# their clocks at night or at the morning sight so that, given the ship's
+# speed and direction, it would be 12 o'clock when the Sun crossed the ship's
+# meridian (12 o'clock = local apparent noon). During 1917, at the
+# Anglo-French Conference on Time-keeping at Sea, it was recommended that all
+# ships, both military and civilian, should adopt hourly standard time zones
+# on the high seas. Whenever a ship was within the territorial waters of any
+# nation it would use that nation's standard time. The captain was permitted
+# to change his ship's clocks at a time of his choice following his ship's
+# entry into another zone time--he often chose midnight. These zones were
+# adopted by all major fleets between 1920 and 1925 but not by many
+# independent merchant ships until World War II.
+
+# From Paul Eggert, using references suggested by Oscar van Vlijmen
+# (2005-03-20):
+#
+# The American Practical Navigator (2002)
+# <http://pollux.nss.nima.mil/pubs/pubs_j_apn_sections.html?rid=187>
+# talks only about the 180-degree meridian with respect to ships in
+# international waters; it ignores the international date line.
diff --git a/tools/zoneinfo/tzdata2008h/backward b/tools/zoneinfo/tzdata2008h/backward
new file mode 100644
index 0000000..a65991c
--- /dev/null
+++ b/tools/zoneinfo/tzdata2008h/backward
@@ -0,0 +1,112 @@
+# @(#)backward 8.6
+
+# This file provides links between current names for time zones
+# and their old names. Many names changed in late 1993.
+
+Link Africa/Asmara Africa/Asmera
+Link Africa/Bamako Africa/Timbuktu
+Link America/Argentina/Catamarca America/Argentina/ComodRivadavia
+Link America/Adak America/Atka
+Link America/Argentina/Buenos_Aires America/Buenos_Aires
+Link America/Argentina/Catamarca America/Catamarca
+Link America/Atikokan America/Coral_Harbour
+Link America/Argentina/Cordoba America/Cordoba
+Link America/Tijuana America/Ensenada
+Link America/Indiana/Indianapolis America/Fort_Wayne
+Link America/Indiana/Indianapolis America/Indianapolis
+Link America/Argentina/Jujuy America/Jujuy
+Link America/Indiana/Knox America/Knox_IN
+Link America/Kentucky/Louisville America/Louisville
+Link America/Argentina/Mendoza America/Mendoza
+Link America/Rio_Branco America/Porto_Acre
+Link America/Argentina/Cordoba America/Rosario
+Link America/St_Thomas America/Virgin
+Link Asia/Ashgabat Asia/Ashkhabad
+Link Asia/Chongqing Asia/Chungking
+Link Asia/Dhaka Asia/Dacca
+Link Asia/Kolkata Asia/Calcutta
+Link Asia/Macau Asia/Macao
+Link Asia/Jerusalem Asia/Tel_Aviv
+Link Asia/Ho_Chi_Minh Asia/Saigon
+Link Asia/Thimphu Asia/Thimbu
+Link Asia/Makassar Asia/Ujung_Pandang
+Link Asia/Ulaanbaatar Asia/Ulan_Bator
+Link Atlantic/Faroe Atlantic/Faeroe
+Link Europe/Oslo Atlantic/Jan_Mayen
+Link Australia/Sydney Australia/ACT
+Link Australia/Sydney Australia/Canberra
+Link Australia/Lord_Howe Australia/LHI
+Link Australia/Sydney Australia/NSW
+Link Australia/Darwin Australia/North
+Link Australia/Brisbane Australia/Queensland
+Link Australia/Adelaide Australia/South
+Link Australia/Hobart Australia/Tasmania
+Link Australia/Melbourne Australia/Victoria
+Link Australia/Perth Australia/West
+Link Australia/Broken_Hill Australia/Yancowinna
+Link America/Rio_Branco Brazil/Acre
+Link America/Noronha Brazil/DeNoronha
+Link America/Sao_Paulo Brazil/East
+Link America/Manaus Brazil/West
+Link America/Halifax Canada/Atlantic
+Link America/Winnipeg Canada/Central
+Link America/Regina Canada/East-Saskatchewan
+Link America/Toronto Canada/Eastern
+Link America/Edmonton Canada/Mountain
+Link America/St_Johns Canada/Newfoundland
+Link America/Vancouver Canada/Pacific
+Link America/Regina Canada/Saskatchewan
+Link America/Whitehorse Canada/Yukon
+Link America/Santiago Chile/Continental
+Link Pacific/Easter Chile/EasterIsland
+Link America/Havana Cuba
+Link Africa/Cairo Egypt
+Link Europe/Dublin Eire
+Link Europe/London Europe/Belfast
+Link Europe/Chisinau Europe/Tiraspol
+Link Europe/London GB
+Link Europe/London GB-Eire
+Link Etc/GMT GMT+0
+Link Etc/GMT GMT-0
+Link Etc/GMT GMT0
+Link Etc/GMT Greenwich
+Link Asia/Hong_Kong Hongkong
+Link Atlantic/Reykjavik Iceland
+Link Asia/Tehran Iran
+Link Asia/Jerusalem Israel
+Link America/Jamaica Jamaica
+Link Asia/Tokyo Japan
+Link Pacific/Kwajalein Kwajalein
+Link Africa/Tripoli Libya
+Link America/Tijuana Mexico/BajaNorte
+Link America/Mazatlan Mexico/BajaSur
+Link America/Mexico_City Mexico/General
+Link Pacific/Auckland NZ
+Link Pacific/Chatham NZ-CHAT
+Link America/Denver Navajo
+Link Asia/Shanghai PRC
+Link Pacific/Pago_Pago Pacific/Samoa
+Link Pacific/Truk Pacific/Yap
+Link Europe/Warsaw Poland
+Link Europe/Lisbon Portugal
+Link Asia/Taipei ROC
+Link Asia/Seoul ROK
+Link Asia/Singapore Singapore
+Link Europe/Istanbul Turkey
+Link Etc/UCT UCT
+Link America/Anchorage US/Alaska
+Link America/Adak US/Aleutian
+Link America/Phoenix US/Arizona
+Link America/Chicago US/Central
+Link America/Indiana/Indianapolis US/East-Indiana
+Link America/New_York US/Eastern
+Link Pacific/Honolulu US/Hawaii
+Link America/Indiana/Knox US/Indiana-Starke
+Link America/Detroit US/Michigan
+Link America/Denver US/Mountain
+Link America/Los_Angeles US/Pacific
+Link Pacific/Pago_Pago US/Samoa
+Link Etc/UTC UTC
+Link Etc/UTC Universal
+Link Europe/Moscow W-SU
+Link Etc/UTC Zulu
diff --git a/tools/zoneinfo/tzdata2008h/etcetera b/tools/zoneinfo/tzdata2008h/etcetera
new file mode 100644
index 0000000..cddbe8a
--- /dev/null
+++ b/tools/zoneinfo/tzdata2008h/etcetera
@@ -0,0 +1,80 @@
+# @(#)etcetera 8.1
+
+# These entries are mostly present for historical reasons, so that
+# people in areas not otherwise covered by the tz files could "zic -l"
+# to a time zone that was right for their area. These days, the
+# tz files cover almost all the inhabited world, and the only practical
+# need now for the entries that are not on UTC are for ships at sea
+# that cannot use POSIX TZ settings.
+
+Zone Etc/GMT 0 - GMT
+Zone Etc/UTC 0 - UTC
+Zone Etc/UCT 0 - UCT
+
+# The following link uses older naming conventions,
+# but it belongs here, not in the file `backward',
+# as functions like gmtime load the "GMT" file to handle leap seconds properly.
+# We want this to work even on installations that omit the other older names.
+Link Etc/GMT GMT
+
+Link Etc/UTC Etc/Universal
+Link Etc/UTC Etc/Zulu
+
+Link Etc/GMT Etc/Greenwich
+Link Etc/GMT Etc/GMT-0
+Link Etc/GMT Etc/GMT+0
+Link Etc/GMT Etc/GMT0
+
+# We use POSIX-style signs in the Zone names and the output abbreviations,
+# even though this is the opposite of what many people expect.
+# POSIX has positive signs west of Greenwich, but many people expect
+# positive signs east of Greenwich. For example, TZ='Etc/GMT+4' uses
+# the abbreviation "GMT+4" and corresponds to 4 hours behind UTC
+# (i.e. west of Greenwich) even though many people would expect it to
+# mean 4 hours ahead of UTC (i.e. east of Greenwich).
+#
+# In the draft 5 of POSIX 1003.1-200x, the angle bracket notation
+# (which is not yet supported by the tz code) allows for
+# TZ='<GMT-4>+4'; if you want time zone abbreviations conforming to
+# ISO 8601 you can use TZ='<-0400>+4'. Thus the commonly-expected
+# offset is kept within the angle bracket (and is used for display)
+# while the POSIX sign is kept outside the angle bracket (and is used
+# for calculation).
+#
+# Do not use a TZ setting like TZ='GMT+4', which is four hours behind
+# GMT but uses the completely misleading abbreviation "GMT".
+
+# Earlier incarnations of this package were not POSIX-compliant,
+# and had lines such as
+# Zone GMT-12 -12 - GMT-1200
+# We did not want things to change quietly if someone accustomed to the old
+# way does a
+# zic -l GMT-12
+# so we moved the names into the Etc subdirectory.
+
+Zone Etc/GMT-14 14 - GMT-14 # 14 hours ahead of GMT
+Zone Etc/GMT-13 13 - GMT-13
+Zone Etc/GMT-12 12 - GMT-12
+Zone Etc/GMT-11 11 - GMT-11
+Zone Etc/GMT-10 10 - GMT-10
+Zone Etc/GMT-9 9 - GMT-9
+Zone Etc/GMT-8 8 - GMT-8
+Zone Etc/GMT-7 7 - GMT-7
+Zone Etc/GMT-6 6 - GMT-6
+Zone Etc/GMT-5 5 - GMT-5
+Zone Etc/GMT-4 4 - GMT-4
+Zone Etc/GMT-3 3 - GMT-3
+Zone Etc/GMT-2 2 - GMT-2
+Zone Etc/GMT-1 1 - GMT-1
+Zone Etc/GMT+1 -1 - GMT+1
+Zone Etc/GMT+2 -2 - GMT+2
+Zone Etc/GMT+3 -3 - GMT+3
+Zone Etc/GMT+4 -4 - GMT+4
+Zone Etc/GMT+5 -5 - GMT+5
+Zone Etc/GMT+6 -6 - GMT+6
+Zone Etc/GMT+7 -7 - GMT+7
+Zone Etc/GMT+8 -8 - GMT+8
+Zone Etc/GMT+9 -9 - GMT+9
+Zone Etc/GMT+10 -10 - GMT+10
+Zone Etc/GMT+11 -11 - GMT+11
+Zone Etc/GMT+12 -12 - GMT+12
diff --git a/tools/zoneinfo/tzdata2008h/europe b/tools/zoneinfo/tzdata2008h/europe
new file mode 100644
index 0000000..7bb9864
--- /dev/null
+++ b/tools/zoneinfo/tzdata2008h/europe
@@ -0,0 +1,2594 @@
+# @(#)europe 8.18
+# <pre>
+
+# This data is by no means authoritative; if you think you know better,
+# go ahead and edit the file (and please send any changes to
+# tz@elsie.nci.nih.gov for general use in the future).
+
+# From Paul Eggert (2006-03-22):
+# A good source for time zone historical data outside the U.S. is
+# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
+# San Diego: ACS Publications, Inc. (2003).
+#
+# Gwillim Law writes that a good source
+# for recent time zone data is the International Air Transport
+# Association's Standard Schedules Information Manual (IATA SSIM),
+# published semiannually. Law sent in several helpful summaries
+# of the IATA's data after 1990.
+#
+# Except where otherwise noted, Shanks & Pottenger is the source for
+# entries through 1991, and IATA SSIM is the source for entries afterwards.
+#
+# Other sources occasionally used include:
+#
+# Edward W. Whitman, World Time Differences,
+# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated),
+# which I found in the UCLA library.
+#
+# <a href="http://www.pettswoodvillage.co.uk/Daylight_Savings_William_Willett.pdf">
+# William Willett, The Waste of Daylight, 19th edition
+# </a> (1914-03)
+#
+# Brazil's Departamento Servico da Hora (DSH),
+# <a href="http://pcdsh01.on.br/HISTHV.htm">
+# History of Summer Time
+# </a> (1998-09-21, in Portuguese)
+
+#
+# I invented the abbreviations marked `*' in the following table;
+# the rest are from earlier versions of this file, or from other sources.
+# Corrections are welcome!
+# std dst 2dst
+# LMT Local Mean Time
+# -4:00 AST ADT Atlantic
+# -3:00 WGT WGST Western Greenland*
+# -1:00 EGT EGST Eastern Greenland*
+# 0:00 GMT BST BDST Greenwich, British Summer
+# 0:00 GMT IST Greenwich, Irish Summer
+# 0:00 WET WEST WEMT Western Europe
+# 0:19:32.13 AMT NST Amsterdam, Netherlands Summer (1835-1937)*
+# 0:20 NET NEST Netherlands (1937-1940)*
+# 1:00 CET CEST CEMT Central Europe
+# 1:00:14 SET Swedish (1879-1899)*
+# 2:00 EET EEST Eastern Europe
+# 3:00 MSK MSD Moscow
+#
+# A reliable and entertaining source about time zones, especially in Britain,
+# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
+
+# From Peter Ilieve (1994-12-04),
+# The original six [EU members]: Belgium, France, (West) Germany, Italy,
+# Luxembourg, the Netherlands.
+# Plus, from 1 Jan 73: Denmark, Ireland, United Kingdom.
+# Plus, from 1 Jan 81: Greece.
+# Plus, from 1 Jan 86: Spain, Portugal.
+# Plus, from 1 Jan 95: Austria, Finland, Sweden. (Norway negotiated terms for
+# entry but in a referendum on 28 Nov 94 the people voted No by 52.2% to 47.8%
+# on a turnout of 88.6%. This was almost the same result as Norway's previous
+# referendum in 1972, they are the only country to have said No twice.
+# Referendums in the other three countries voted Yes.)
+# ...
+# Estonia ... uses EU dates but not at 01:00 GMT, they use midnight GMT.
+# I don't think they know yet what they will do from 1996 onwards.
+# ...
+# There shouldn't be any [current members who are not using EU rules].
+# A Directive has the force of law, member states are obliged to enact
+# national law to implement it. The only contentious issue was the
+# different end date for the UK and Ireland, and this was always allowed
+# in the Directive.
+
+
+###############################################################################
+
+# Britain (United Kingdom) and Ireland (Eire)
+
+# From Peter Ilieve (1994-07-06):
+#
+# On 17 Jan 1994 the Independent, a UK quality newspaper, had a piece about
+# historical vistas along the Thames in west London. There was a photo
+# and a sketch map showing some of the sightlines involved. One paragraph
+# of the text said:
+#
+# `An old stone obelisk marking a forgotten terrestrial meridian stands
+# beside the river at Kew. In the 18th century, before time and longitude
+# was standardised by the Royal Observatory in Greenwich, scholars observed
+# this stone and the movement of stars from Kew Observatory nearby. They
+# made their calculations and set the time for the Horse Guards and Parliament,
+# but now the stone is obscured by scrubwood and can only be seen by walking
+# along the towpath within a few yards of it.'
+#
+# I have a one inch to one mile map of London and my estimate of the stone's
+# position is 51 deg. 28' 30" N, 0 deg. 18' 45" W. The longitude should
+# be within about +-2". The Ordnance Survey grid reference is TQ172761.
+#
+# [This yields GMTOFF = -0:01:15 for London LMT in the 18th century.]
+
+# From Paul Eggert (1993-11-18):
+#
+# Howse writes that Britain was the first country to use standard time.
+# The railways cared most about the inconsistencies of local mean time,
+# and it was they who forced a uniform time on the country.
+# The original idea was credited to Dr. William Hyde Wollaston (1766-1828)
+# and was popularized by Abraham Follett Osler (1808-1903).
+# The first railway to adopt London time was the Great Western Railway
+# in November 1840; other railways followed suit, and by 1847 most
+# (though not all) railways used London time. On 1847-09-22 the
+# Railway Clearing House, an industry standards body, recommended that GMT be
+# adopted at all stations as soon as the General Post Office permitted it.
+# The transition occurred on 12-01 for the L&NW, the Caledonian,
+# and presumably other railways; the January 1848 Bradshaw's lists many
+# railways as using GMT. By 1855 the vast majority of public
+# clocks in Britain were set to GMT (though some, like the great clock
+# on Tom Tower at Christ Church, Oxford, were fitted with two minute hands,
+# one for local time and one for GMT). The last major holdout was the legal
+# system, which stubbornly stuck to local time for many years, leading
+# to oddities like polls opening at 08:13 and closing at 16:13.
+# The legal system finally switched to GMT when the Statutes (Definition
+# of Time) Act took effect; it received the Royal Assent on 1880-08-02.
+#
+# In the tables below, we condense this complicated story into a single
+# transition date for London, namely 1847-12-01. We don't know as much
+# about Dublin, so we use 1880-08-02, the legal transition time.
+
+# From Paul Eggert (2003-09-27):
+# Summer Time was first seriously proposed by William Willett (1857-1915),
+# a London builder and member of the Royal Astronomical Society
+# who circulated a pamphlet ``The Waste of Daylight'' (1907)
+# that proposed advancing clocks 20 minutes on each of four Sundays in April,
+# and retarding them by the same amount on four Sundays in September.
+# A bill was drafted in 1909 and introduced in Parliament several times,
+# but it met with ridicule and opposition, especially from farming interests.
+# Later editions of the pamphlet proposed one-hour summer time, and
+# it was eventually adopted as a wartime measure in 1916.
+# See: Summer Time Arrives Early, The Times (2000-05-18).
+# A monument to Willett was unveiled on 1927-05-21, in an open space in
+# a 45-acre wood near Chislehurst, Kent that was purchased by popular
+# subscription and open to the public. On the south face of the monolith,
+# designed by G. W. Miller, is the the William Willett Memorial Sundial,
+# which is permanently set to Summer Time.
+
+# From Winston Churchill (1934-04-28):
+# It is one of the paradoxes of history that we should owe the boon of
+# summer time, which gives every year to the people of this country
+# between 160 and 170 hours more daylight leisure, to a war which
+# plunged Europe into darkness for four years, and shook the
+# foundations of civilization throughout the world.
+# -- <a href="http://www.winstonchurchill.org/fh114willett.htm">
+# "A Silent Toast to William Willett", Pictorial Weekly
+# </a>
+
+# From Paul Eggert (1996-09-03):
+# The OED Supplement says that the English originally said ``Daylight Saving''
+# when they were debating the adoption of DST in 1908; but by 1916 this
+# term appears only in quotes taken from DST's opponents, whereas the
+# proponents (who eventually won the argument) are quoted as using ``Summer''.
+
+# From Arthur David Olson (1989-01-19):
+#
+# A source at the British Information Office in New York avers that it's
+# known as "British" Summer Time in all parts of the United Kingdom.
+
+# Date: 4 Jan 89 08:57:25 GMT (Wed)
+# From: Jonathan Leffler
+# [British Summer Time] is fixed annually by Act of Parliament.
+# If you can predict what Parliament will do, you should be in
+# politics making a fortune, not computing.
+
+# From Chris Carrier (1996-06-14):
+# I remember reading in various wartime issues of the London Times the
+# acronym BDST for British Double Summer Time. Look for the published
+# time of sunrise and sunset in The Times, when BDST was in effect, and
+# if you find a zone reference it will say, "All times B.D.S.T."
+
+# From Joseph S. Myers (1999-09-02):
+# ... some military cables (WO 219/4100 - this is a copy from the
+# main SHAEF archives held in the US National Archives, SHAEF/5252/8/516)
+# agree that the usage is BDST (this appears in a message dated 17 Feb 1945).
+
+# From Joseph S. Myers (2000-10-03):
+# On 18th April 1941, Sir Stephen Tallents of the BBC wrote to Sir
+# Alexander Maxwell of the Home Office asking whether there was any
+# official designation; the reply of the 21st was that there wasn't
+# but he couldn't think of anything better than the "Double British
+# Summer Time" that the BBC had been using informally.
+# http://student.cusu.cam.ac.uk/~jsm28/british-time/bbc-19410418.png
+# http://student.cusu.cam.ac.uk/~jsm28/british-time/ho-19410421.png
+
+# From Sir Alexander Maxwell in the above-mentioned letter (1941-04-21):
+# [N]o official designation has as far as I know been adopted for the time
+# which is to be introduced in May....
+# I cannot think of anything better than "Double British Summer Time"
+# which could not be said to run counter to any official description.
+
+# From Paul Eggert (2000-10-02):
+# Howse writes (p 157) `DBST' too, but `BDST' seems to have been common
+# and follows the more usual convention of putting the location name first,
+# so we use `BDST'.
+
+# Peter Ilieve (1998-04-19) described at length
+# the history of summer time legislation in the United Kingdom.
+# Since 1998 Joseph S. Myers has been updating
+# and extending this list, which can be found in
+# <a href="http://student.cusu.cam.ac.uk/~jsm28/british-time/">
+# History of legal time in Britain
+# </a>
+
+# From Joseph S. Myers (1998-01-06):
+#
+# The legal time in the UK outside of summer time is definitely GMT, not UTC;
+# see Lord Tanlaw's speech
+# <a href="http://www.parliament.the-stationery-office.co.uk/pa/ld199697/ldhansrd/pdvn/lds97/text/70611-20.htm#70611-20_head0">
+# (Lords Hansard 11 June 1997 columns 964 to 976)
+# </a>.
+
+# From Paul Eggert (2006-03-22):
+#
+# For lack of other data, follow Shanks & Pottenger for Eire in 1940-1948.
+#
+# Given Ilieve and Myers's data, the following claims by Shanks & Pottenger
+# are incorrect:
+# * Wales did not switch from GMT to daylight saving time until
+# 1921 Apr 3, when they began to conform with the rest of Great Britain.
+# Actually, Wales was identical after 1880.
+# * Eire had two transitions on 1916 Oct 1.
+# It actually just had one transition.
+# * Northern Ireland used single daylight saving time throughout WW II.
+# Actually, it conformed to Britain.
+# * GB-Eire changed standard time to 1 hour ahead of GMT on 1968-02-18.
+# Actually, that date saw the usual switch to summer time.
+# Standard time was not changed until 1968-10-27 (the clocks didn't change).
+#
+# Here is another incorrect claim by Shanks & Pottenger:
+# * Jersey, Guernsey, and the Isle of Man did not switch from GMT
+# to daylight saving time until 1921 Apr 3, when they began to
+# conform with Great Britain.
+# S.R.&O. 1916, No. 382 and HO 45/10811/312364 (quoted above) say otherwise.
+#
+# The following claim by Shanks & Pottenger is possible though doubtful;
+# we'll ignore it for now.
+# * Dublin's 1971-10-31 switch was at 02:00, even though London's was 03:00.
+#
+#
+# Whitman says Dublin Mean Time was -0:25:21, which is more precise than
+# Shanks & Pottenger.
+# Perhaps this was Dunsink Observatory Time, as Dunsink Observatory
+# (8 km NW of Dublin's center) seemingly was to Dublin as Greenwich was
+# to London. For example:
+#
+# "Timeball on the ballast office is down. Dunsink time."
+# -- James Joyce, Ulysses
+
+# From Joseph S. Myers (2005-01-26):
+# Irish laws are available online at www.irishstatutebook.ie. These include
+# various relating to legal time, for example:
+#
+# ZZA13Y1923.html ZZA12Y1924.html ZZA8Y1925.html ZZSIV20PG1267.html
+#
+# ZZSI71Y1947.html ZZSI128Y1948.html ZZSI23Y1949.html ZZSI41Y1950.html
+# ZZSI27Y1951.html ZZSI73Y1952.html
+#
+# ZZSI11Y1961.html ZZSI232Y1961.html ZZSI182Y1962.html
+# ZZSI167Y1963.html ZZSI257Y1964.html ZZSI198Y1967.html
+# ZZA23Y1968.html ZZA17Y1971.html
+#
+# ZZSI67Y1981.html ZZSI212Y1982.html ZZSI45Y1986.html
+# ZZSI264Y1988.html ZZSI52Y1990.html ZZSI371Y1992.html
+# ZZSI395Y1994.html ZZSI484Y1997.html ZZSI506Y2001.html
+#
+# [These are all relative to the root, e.g., the first is
+# <http://www.irishstatutebook.ie/ZZA13Y1923.html>.]
+#
+# (These are those I found, but there could be more. In any case these
+# should allow various updates to the comments in the europe file to cover
+# the laws applicable in Ireland.)
+#
+# (Note that the time in the Republic of Ireland since 1968 has been defined
+# in terms of standard time being GMT+1 with a period of winter time when it
+# is GMT, rather than standard time being GMT with a period of summer time
+# being GMT+1.)
+
+# From Paul Eggert (1999-03-28):
+# Clive Feather (<news:859845706.26043.0@office.demon.net>, 1997-03-31)
+# reports that Folkestone (Cheriton) Shuttle Terminal uses Concession Time
+# (CT), equivalent to French civil time.
+# Julian Hill (<news:36118128.5A14@virgin.net>, 1998-09-30) reports that
+# trains between Dollands Moor (the freight facility next door)
+# and Frethun run in CT.
+# My admittedly uninformed guess is that the terminal has two authorities,
+# the French concession operators and the British civil authorities,
+# and that the time depends on who you're talking to.
+# If, say, the British police were called to the station for some reason,
+# I would expect the official police report to use GMT/BST and not CET/CEST.
+# This is a borderline case, but for now let's stick to GMT/BST.
+
+# From an anonymous contributor (1996-06-02):
+# The law governing time in Ireland is under Statutory Instrument SI 395/94,
+# which gives force to European Union 7th Council Directive # 94/21/EC.
+# Under this directive, the Minister for Justice in Ireland makes appropriate
+# regulations. I spoke this morning with the Secretary of the Department of
+# Justice (tel +353 1 678 9711) who confirmed to me that the correct name is
+# "Irish Summer Time", abbreviated to "IST".
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+# Summer Time Act, 1916
+Rule GB-Eire 1916 only - May 21 2:00s 1:00 BST
+Rule GB-Eire 1916 only - Oct 1 2:00s 0 GMT
+# S.R.&O. 1917, No. 358
+Rule GB-Eire 1917 only - Apr 8 2:00s 1:00 BST
+Rule GB-Eire 1917 only - Sep 17 2:00s 0 GMT
+# S.R.&O. 1918, No. 274
+Rule GB-Eire 1918 only - Mar 24 2:00s 1:00 BST
+Rule GB-Eire 1918 only - Sep 30 2:00s 0 GMT
+# S.R.&O. 1919, No. 297
+Rule GB-Eire 1919 only - Mar 30 2:00s 1:00 BST
+Rule GB-Eire 1919 only - Sep 29 2:00s 0 GMT
+# S.R.&O. 1920, No. 458
+Rule GB-Eire 1920 only - Mar 28 2:00s 1:00 BST
+# S.R.&O. 1920, No. 1844
+Rule GB-Eire 1920 only - Oct 25 2:00s 0 GMT
+# S.R.&O. 1921, No. 363
+Rule GB-Eire 1921 only - Apr 3 2:00s 1:00 BST
+Rule GB-Eire 1921 only - Oct 3 2:00s 0 GMT
+# S.R.&O. 1922, No. 264
+Rule GB-Eire 1922 only - Mar 26 2:00s 1:00 BST
+Rule GB-Eire 1922 only - Oct 8 2:00s 0 GMT
+# The Summer Time Act, 1922
+Rule GB-Eire 1923 only - Apr Sun>=16 2:00s 1:00 BST
+Rule GB-Eire 1923 1924 - Sep Sun>=16 2:00s 0 GMT
+Rule GB-Eire 1924 only - Apr Sun>=9 2:00s 1:00 BST
+Rule GB-Eire 1925 1926 - Apr Sun>=16 2:00s 1:00 BST
+# The Summer Time Act, 1925
+Rule GB-Eire 1925 1938 - Oct Sun>=2 2:00s 0 GMT
+Rule GB-Eire 1927 only - Apr Sun>=9 2:00s 1:00 BST
+Rule GB-Eire 1928 1929 - Apr Sun>=16 2:00s 1:00 BST
+Rule GB-Eire 1930 only - Apr Sun>=9 2:00s 1:00 BST
+Rule GB-Eire 1931 1932 - Apr Sun>=16 2:00s 1:00 BST
+Rule GB-Eire 1933 only - Apr Sun>=9 2:00s 1:00 BST
+Rule GB-Eire 1934 only - Apr Sun>=16 2:00s 1:00 BST
+Rule GB-Eire 1935 only - Apr Sun>=9 2:00s 1:00 BST
+Rule GB-Eire 1936 1937 - Apr Sun>=16 2:00s 1:00 BST
+Rule GB-Eire 1938 only - Apr Sun>=9 2:00s 1:00 BST
+Rule GB-Eire 1939 only - Apr Sun>=16 2:00s 1:00 BST
+# S.R.&O. 1939, No. 1379
+Rule GB-Eire 1939 only - Nov Sun>=16 2:00s 0 GMT
+# S.R.&O. 1940, No. 172 and No. 1883
+Rule GB-Eire 1940 only - Feb Sun>=23 2:00s 1:00 BST
+# S.R.&O. 1941, No. 476
+Rule GB-Eire 1941 only - May Sun>=2 1:00s 2:00 BDST
+Rule GB-Eire 1941 1943 - Aug Sun>=9 1:00s 1:00 BST
+# S.R.&O. 1942, No. 506
+Rule GB-Eire 1942 1944 - Apr Sun>=2 1:00s 2:00 BDST
+# S.R.&O. 1944, No. 932
+Rule GB-Eire 1944 only - Sep Sun>=16 1:00s 1:00 BST
+# S.R.&O. 1945, No. 312
+Rule GB-Eire 1945 only - Apr Mon>=2 1:00s 2:00 BDST
+Rule GB-Eire 1945 only - Jul Sun>=9 1:00s 1:00 BST
+# S.R.&O. 1945, No. 1208
+Rule GB-Eire 1945 1946 - Oct Sun>=2 2:00s 0 GMT
+Rule GB-Eire 1946 only - Apr Sun>=9 2:00s 1:00 BST
+# The Summer Time Act, 1947
+Rule GB-Eire 1947 only - Mar 16 2:00s 1:00 BST
+Rule GB-Eire 1947 only - Apr 13 1:00s 2:00 BDST
+Rule GB-Eire 1947 only - Aug 10 1:00s 1:00 BST
+Rule GB-Eire 1947 only - Nov 2 2:00s 0 GMT
+# Summer Time Order, 1948 (S.I. 1948/495)
+Rule GB-Eire 1948 only - Mar 14 2:00s 1:00 BST
+Rule GB-Eire 1948 only - Oct 31 2:00s 0 GMT
+# Summer Time Order, 1949 (S.I. 1949/373)
+Rule GB-Eire 1949 only - Apr 3 2:00s 1:00 BST
+Rule GB-Eire 1949 only - Oct 30 2:00s 0 GMT
+# Summer Time Order, 1950 (S.I. 1950/518)
+# Summer Time Order, 1951 (S.I. 1951/430)
+# Summer Time Order, 1952 (S.I. 1952/451)
+Rule GB-Eire 1950 1952 - Apr Sun>=14 2:00s 1:00 BST
+Rule GB-Eire 1950 1952 - Oct Sun>=21 2:00s 0 GMT
+# revert to the rules of the Summer Time Act, 1925
+Rule GB-Eire 1953 only - Apr Sun>=16 2:00s 1:00 BST
+Rule GB-Eire 1953 1960 - Oct Sun>=2 2:00s 0 GMT
+Rule GB-Eire 1954 only - Apr Sun>=9 2:00s 1:00 BST
+Rule GB-Eire 1955 1956 - Apr Sun>=16 2:00s 1:00 BST
+Rule GB-Eire 1957 only - Apr Sun>=9 2:00s 1:00 BST
+Rule GB-Eire 1958 1959 - Apr Sun>=16 2:00s 1:00 BST
+Rule GB-Eire 1960 only - Apr Sun>=9 2:00s 1:00 BST
+# Summer Time Order, 1961 (S.I. 1961/71)
+# Summer Time (1962) Order, 1961 (S.I. 1961/2465)
+# Summer Time Order, 1963 (S.I. 1963/81)
+Rule GB-Eire 1961 1963 - Mar lastSun 2:00s 1:00 BST
+Rule GB-Eire 1961 1968 - Oct Sun>=23 2:00s 0 GMT
+# Summer Time (1964) Order, 1963 (S.I. 1963/2101)
+# Summer Time Order, 1964 (S.I. 1964/1201)
+# Summer Time Order, 1967 (S.I. 1967/1148)
+Rule GB-Eire 1964 1967 - Mar Sun>=19 2:00s 1:00 BST
+# Summer Time Order, 1968 (S.I. 1968/117)
+Rule GB-Eire 1968 only - Feb 18 2:00s 1:00 BST
+# The British Standard Time Act, 1968
+# (no summer time)
+# The Summer Time Act, 1972
+Rule GB-Eire 1972 1980 - Mar Sun>=16 2:00s 1:00 BST
+Rule GB-Eire 1972 1980 - Oct Sun>=23 2:00s 0 GMT
+# Summer Time Order, 1980 (S.I. 1980/1089)
+# Summer Time Order, 1982 (S.I. 1982/1673)
+# Summer Time Order, 1986 (S.I. 1986/223)
+# Summer Time Order, 1988 (S.I. 1988/931)
+Rule GB-Eire 1981 1995 - Mar lastSun 1:00u 1:00 BST
+Rule GB-Eire 1981 1989 - Oct Sun>=23 1:00u 0 GMT
+# Summer Time Order, 1989 (S.I. 1989/985)
+# Summer Time Order, 1992 (S.I. 1992/1729)
+# Summer Time Order 1994 (S.I. 1994/2798)
+Rule GB-Eire 1990 1995 - Oct Sun>=22 1:00u 0 GMT
+# Summer Time Order 1997 (S.I. 1997/2982)
+# See EU for rules starting in 1996.
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/London -0:01:15 - LMT 1847 Dec 1 0:00s
+ 0:00 GB-Eire %s 1968 Oct 27
+ 1:00 - BST 1971 Oct 31 2:00u
+ 0:00 GB-Eire %s 1996
+ 0:00 EU GMT/BST
+Link Europe/London Europe/Jersey
+Link Europe/London Europe/Guernsey
+Link Europe/London Europe/Isle_of_Man
+Zone Europe/Dublin -0:25:00 - LMT 1880 Aug 2
+ -0:25:21 - DMT 1916 May 21 2:00
+ -0:25:21 1:00 IST 1916 Oct 1 2:00s
+ 0:00 GB-Eire %s 1921 Dec 6 # independence
+ 0:00 GB-Eire GMT/IST 1940 Feb 25 2:00
+ 0:00 1:00 IST 1946 Oct 6 2:00
+ 0:00 - GMT 1947 Mar 16 2:00
+ 0:00 1:00 IST 1947 Nov 2 2:00
+ 0:00 - GMT 1948 Apr 18 2:00
+ 0:00 GB-Eire GMT/IST 1968 Oct 27
+ 1:00 - IST 1971 Oct 31 2:00u
+ 0:00 GB-Eire GMT/IST 1996
+ 0:00 EU GMT/IST
+
+###############################################################################
+
+# Europe
+
+# EU rules are for the European Union, previously known as the EC, EEC,
+# Common Market, etc.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule EU 1977 1980 - Apr Sun>=1 1:00u 1:00 S
+Rule EU 1977 only - Sep lastSun 1:00u 0 -
+Rule EU 1978 only - Oct 1 1:00u 0 -
+Rule EU 1979 1995 - Sep lastSun 1:00u 0 -
+Rule EU 1981 max - Mar lastSun 1:00u 1:00 S
+Rule EU 1996 max - Oct lastSun 1:00u 0 -
+# The most recent directive covers the years starting in 2002. See:
+# <a href="http://europa.eu.int/eur-lex/en/lif/dat/2000/en_300L0084.html">
+# Directive 2000/84/EC of the European Parliament and of the Council
+# of 19 January 2001 on summer-time arrangements.
+# </a>
+
+# W-Eur differs from EU only in that W-Eur uses standard time.
+Rule W-Eur 1977 1980 - Apr Sun>=1 1:00s 1:00 S
+Rule W-Eur 1977 only - Sep lastSun 1:00s 0 -
+Rule W-Eur 1978 only - Oct 1 1:00s 0 -
+Rule W-Eur 1979 1995 - Sep lastSun 1:00s 0 -
+Rule W-Eur 1981 max - Mar lastSun 1:00s 1:00 S
+Rule W-Eur 1996 max - Oct lastSun 1:00s 0 -
+
+# Older C-Eur rules are for convenience in the tables.
+# From 1977 on, C-Eur differs from EU only in that C-Eur uses standard time.
+Rule C-Eur 1916 only - Apr 30 23:00 1:00 S
+Rule C-Eur 1916 only - Oct 1 1:00 0 -
+Rule C-Eur 1917 1918 - Apr Mon>=15 2:00s 1:00 S
+Rule C-Eur 1917 1918 - Sep Mon>=15 2:00s 0 -
+Rule C-Eur 1940 only - Apr 1 2:00s 1:00 S
+Rule C-Eur 1942 only - Nov 2 2:00s 0 -
+Rule C-Eur 1943 only - Mar 29 2:00s 1:00 S
+Rule C-Eur 1943 only - Oct 4 2:00s 0 -
+Rule C-Eur 1944 1945 - Apr Mon>=1 2:00s 1:00 S
+# Whitman gives 1944 Oct 7; go with Shanks & Pottenger.
+Rule C-Eur 1944 only - Oct 2 2:00s 0 -
+# From Jesper Norgaard Welen (2008-07-13):
+#
+# I found what is probably a typo of 2:00 which should perhaps be 2:00s
+# in the C-Eur rule from tz database version 2008d (this part was
+# corrected in version 2008d). The circumstancial evidence is simply the
+# tz database itself, as seen below:
+#
+# Zone Europe/Paris 0:09:21 - LMT 1891 Mar 15 0:01
+# 0:00 France WE%sT 1945 Sep 16 3:00
+#
+# Zone Europe/Monaco 0:29:32 - LMT 1891 Mar 15
+# 0:00 France WE%sT 1945 Sep 16 3:00
+#
+# Zone Europe/Belgrade 1:22:00 - LMT 1884
+# 1:00 1:00 CEST 1945 Sep 16 2:00s
+#
+# Rule France 1945 only - Sep 16 3:00 0 -
+# Rule Belgium 1945 only - Sep 16 2:00s 0 -
+# Rule Neth 1945 only - Sep 16 2:00s 0 -
+#
+# The rule line to be changed is:
+#
+# Rule C-Eur 1945 only - Sep 16 2:00 0 -
+#
+# It seems that Paris, Monaco, Rule France, Rule Belgium all agree on
+# 2:00 standard time, e.g. 3:00 local time. However there are no
+# countries that use C-Eur rules in September 1945, so the only items
+# affected are apparently these ficticious zones that translates acronyms
+# CET and MET:
+#
+# Zone CET 1:00 C-Eur CE%sT
+# Zone MET 1:00 C-Eur ME%sT
+#
+# It this is right then the corrected version would look like:
+#
+# Rule C-Eur 1945 only - Sep 16 2:00s 0 -
+#
+# A small step for mankind though 8-)
+Rule C-Eur 1945 only - Sep 16 2:00s 0 -
+Rule C-Eur 1977 1980 - Apr Sun>=1 2:00s 1:00 S
+Rule C-Eur 1977 only - Sep lastSun 2:00s 0 -
+Rule C-Eur 1978 only - Oct 1 2:00s 0 -
+Rule C-Eur 1979 1995 - Sep lastSun 2:00s 0 -
+Rule C-Eur 1981 max - Mar lastSun 2:00s 1:00 S
+Rule C-Eur 1996 max - Oct lastSun 2:00s 0 -
+
+# E-Eur differs from EU only in that E-Eur switches at midnight local time.
+Rule E-Eur 1977 1980 - Apr Sun>=1 0:00 1:00 S
+Rule E-Eur 1977 only - Sep lastSun 0:00 0 -
+Rule E-Eur 1978 only - Oct 1 0:00 0 -
+Rule E-Eur 1979 1995 - Sep lastSun 0:00 0 -
+Rule E-Eur 1981 max - Mar lastSun 0:00 1:00 S
+Rule E-Eur 1996 max - Oct lastSun 0:00 0 -
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Russia 1917 only - Jul 1 23:00 1:00 MST # Moscow Summer Time
+Rule Russia 1917 only - Dec 28 0:00 0 MMT # Moscow Mean Time
+Rule Russia 1918 only - May 31 22:00 2:00 MDST # Moscow Double Summer Time
+Rule Russia 1918 only - Sep 16 1:00 1:00 MST
+Rule Russia 1919 only - May 31 23:00 2:00 MDST
+Rule Russia 1919 only - Jul 1 2:00 1:00 S
+Rule Russia 1919 only - Aug 16 0:00 0 -
+Rule Russia 1921 only - Feb 14 23:00 1:00 S
+Rule Russia 1921 only - Mar 20 23:00 2:00 M # Midsummer
+Rule Russia 1921 only - Sep 1 0:00 1:00 S
+Rule Russia 1921 only - Oct 1 0:00 0 -
+# Act No.925 of the Council of Ministers of the USSR (1980-10-24):
+Rule Russia 1981 1984 - Apr 1 0:00 1:00 S
+Rule Russia 1981 1983 - Oct 1 0:00 0 -
+# Act No.967 of the Council of Ministers of the USSR (1984-09-13), repeated in
+# Act No.227 of the Council of Ministers of the USSR (1989-03-14):
+Rule Russia 1984 1991 - Sep lastSun 2:00s 0 -
+Rule Russia 1985 1991 - Mar lastSun 2:00s 1:00 S
+#
+Rule Russia 1992 only - Mar lastSat 23:00 1:00 S
+Rule Russia 1992 only - Sep lastSat 23:00 0 -
+Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S
+Rule Russia 1993 1995 - Sep lastSun 2:00s 0 -
+Rule Russia 1996 max - Oct lastSun 2:00s 0 -
+
+# These are for backward compatibility with older versions.
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone WET 0:00 EU WE%sT
+Zone CET 1:00 C-Eur CE%sT
+Zone MET 1:00 C-Eur ME%sT
+Zone EET 2:00 EU EE%sT
+
+# Previous editions of this database used abbreviations like MET DST
+# for Central European Summer Time, but this didn't agree with common usage.
+
+# From Markus Kuhn (1996-07-12):
+# The official German names ... are
+#
+# Mitteleuropaeische Zeit (MEZ) = UTC+01:00
+# Mitteleuropaeische Sommerzeit (MESZ) = UTC+02:00
+#
+# as defined in the German Time Act (Gesetz ueber die Zeitbestimmung (ZeitG),
+# 1978-07-25, Bundesgesetzblatt, Jahrgang 1978, Teil I, S. 1110-1111)....
+# I wrote ... to the German Federal Physical-Technical Institution
+#
+# Physikalisch-Technische Bundesanstalt (PTB)
+# Laboratorium 4.41 "Zeiteinheit"
+# Postfach 3345
+# D-38023 Braunschweig
+# phone: +49 531 592-0
+#
+# ... I received today an answer letter from Dr. Peter Hetzel, head of the PTB
+# department for time and frequency transmission. He explained that the
+# PTB translates MEZ and MESZ into English as
+#
+# Central European Time (CET) = UTC+01:00
+# Central European Summer Time (CEST) = UTC+02:00
+
+
+# Albania
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Albania 1940 only - Jun 16 0:00 1:00 S
+Rule Albania 1942 only - Nov 2 3:00 0 -
+Rule Albania 1943 only - Mar 29 2:00 1:00 S
+Rule Albania 1943 only - Apr 10 3:00 0 -
+Rule Albania 1974 only - May 4 0:00 1:00 S
+Rule Albania 1974 only - Oct 2 0:00 0 -
+Rule Albania 1975 only - May 1 0:00 1:00 S
+Rule Albania 1975 only - Oct 2 0:00 0 -
+Rule Albania 1976 only - May 2 0:00 1:00 S
+Rule Albania 1976 only - Oct 3 0:00 0 -
+Rule Albania 1977 only - May 8 0:00 1:00 S
+Rule Albania 1977 only - Oct 2 0:00 0 -
+Rule Albania 1978 only - May 6 0:00 1:00 S
+Rule Albania 1978 only - Oct 1 0:00 0 -
+Rule Albania 1979 only - May 5 0:00 1:00 S
+Rule Albania 1979 only - Sep 30 0:00 0 -
+Rule Albania 1980 only - May 3 0:00 1:00 S
+Rule Albania 1980 only - Oct 4 0:00 0 -
+Rule Albania 1981 only - Apr 26 0:00 1:00 S
+Rule Albania 1981 only - Sep 27 0:00 0 -
+Rule Albania 1982 only - May 2 0:00 1:00 S
+Rule Albania 1982 only - Oct 3 0:00 0 -
+Rule Albania 1983 only - Apr 18 0:00 1:00 S
+Rule Albania 1983 only - Oct 1 0:00 0 -
+Rule Albania 1984 only - Apr 1 0:00 1:00 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Tirane 1:19:20 - LMT 1914
+ 1:00 - CET 1940 Jun 16
+ 1:00 Albania CE%sT 1984 Jul
+ 1:00 EU CE%sT
+
+# Andorra
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Andorra 0:06:04 - LMT 1901
+ 0:00 - WET 1946 Sep 30
+ 1:00 - CET 1985 Mar 31 2:00
+ 1:00 EU CE%sT
+
+# Austria
+
+# From Paul Eggert (2006-03-22): Shanks & Pottenger give 1918-06-16 and
+# 1945-11-18, but the Austrian Federal Office of Metrology and
+# Surveying (BEV) gives 1918-09-16 and for Vienna gives the "alleged"
+# date of 1945-04-12 with no time. For the 1980-04-06 transition
+# Shanks & Pottenger give 02:00, the BEV 00:00. Go with the BEV,
+# and guess 02:00 for 1945-04-12.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Austria 1920 only - Apr 5 2:00s 1:00 S
+Rule Austria 1920 only - Sep 13 2:00s 0 -
+Rule Austria 1946 only - Apr 14 2:00s 1:00 S
+Rule Austria 1946 1948 - Oct Sun>=1 2:00s 0 -
+Rule Austria 1947 only - Apr 6 2:00s 1:00 S
+Rule Austria 1948 only - Apr 18 2:00s 1:00 S
+Rule Austria 1980 only - Apr 6 0:00 1:00 S
+Rule Austria 1980 only - Sep 28 0:00 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Vienna 1:05:20 - LMT 1893 Apr
+ 1:00 C-Eur CE%sT 1920
+ 1:00 Austria CE%sT 1940 Apr 1 2:00s
+ 1:00 C-Eur CE%sT 1945 Apr 2 2:00s
+ 1:00 1:00 CEST 1945 Apr 12 2:00s
+ 1:00 - CET 1946
+ 1:00 Austria CE%sT 1981
+ 1:00 EU CE%sT
+
+# Belarus
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Minsk 1:50:16 - LMT 1880
+ 1:50 - MMT 1924 May 2 # Minsk Mean Time
+ 2:00 - EET 1930 Jun 21
+ 3:00 - MSK 1941 Jun 28
+ 1:00 C-Eur CE%sT 1944 Jul 3
+ 3:00 Russia MSK/MSD 1990
+ 3:00 - MSK 1991 Mar 31 2:00s
+ 2:00 1:00 EEST 1991 Sep 29 2:00s
+ 2:00 - EET 1992 Mar 29 0:00s
+ 2:00 1:00 EEST 1992 Sep 27 0:00s
+ 2:00 Russia EE%sT
+
+# Belgium
+#
+# From Paul Eggert (1997-07-02):
+# Entries from 1918 through 1991 are taken from:
+# Annuaire de L'Observatoire Royal de Belgique,
+# Avenue Circulaire, 3, B-1180 BRUXELLES, CLVIIe annee, 1991
+# (Imprimerie HAYEZ, s.p.r.l., Rue Fin, 4, 1080 BRUXELLES, MCMXC),
+# pp 8-9.
+# LMT before 1892 was 0:17:30, according to the official journal of Belgium:
+# Moniteur Belge, Samedi 30 Avril 1892, N.121.
+# Thanks to Pascal Delmoitie for these references.
+# The 1918 rules are listed for completeness; they apply to unoccupied Belgium.
+# Assume Brussels switched to WET in 1918 when the armistice took effect.
+#
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Belgium 1918 only - Mar 9 0:00s 1:00 S
+Rule Belgium 1918 1919 - Oct Sat>=1 23:00s 0 -
+Rule Belgium 1919 only - Mar 1 23:00s 1:00 S
+Rule Belgium 1920 only - Feb 14 23:00s 1:00 S
+Rule Belgium 1920 only - Oct 23 23:00s 0 -
+Rule Belgium 1921 only - Mar 14 23:00s 1:00 S
+Rule Belgium 1921 only - Oct 25 23:00s 0 -
+Rule Belgium 1922 only - Mar 25 23:00s 1:00 S
+Rule Belgium 1922 1927 - Oct Sat>=1 23:00s 0 -
+Rule Belgium 1923 only - Apr 21 23:00s 1:00 S
+Rule Belgium 1924 only - Mar 29 23:00s 1:00 S
+Rule Belgium 1925 only - Apr 4 23:00s 1:00 S
+# DSH writes that a royal decree of 1926-02-22 specified the Sun following 3rd
+# Sat in Apr (except if it's Easter, in which case it's one Sunday earlier),
+# to Sun following 1st Sat in Oct, and that a royal decree of 1928-09-15
+# changed the transition times to 02:00 GMT.
+Rule Belgium 1926 only - Apr 17 23:00s 1:00 S
+Rule Belgium 1927 only - Apr 9 23:00s 1:00 S
+Rule Belgium 1928 only - Apr 14 23:00s 1:00 S
+Rule Belgium 1928 1938 - Oct Sun>=2 2:00s 0 -
+Rule Belgium 1929 only - Apr 21 2:00s 1:00 S
+Rule Belgium 1930 only - Apr 13 2:00s 1:00 S
+Rule Belgium 1931 only - Apr 19 2:00s 1:00 S
+Rule Belgium 1932 only - Apr 3 2:00s 1:00 S
+Rule Belgium 1933 only - Mar 26 2:00s 1:00 S
+Rule Belgium 1934 only - Apr 8 2:00s 1:00 S
+Rule Belgium 1935 only - Mar 31 2:00s 1:00 S
+Rule Belgium 1936 only - Apr 19 2:00s 1:00 S
+Rule Belgium 1937 only - Apr 4 2:00s 1:00 S
+Rule Belgium 1938 only - Mar 27 2:00s 1:00 S
+Rule Belgium 1939 only - Apr 16 2:00s 1:00 S
+Rule Belgium 1939 only - Nov 19 2:00s 0 -
+Rule Belgium 1940 only - Feb 25 2:00s 1:00 S
+Rule Belgium 1944 only - Sep 17 2:00s 0 -
+Rule Belgium 1945 only - Apr 2 2:00s 1:00 S
+Rule Belgium 1945 only - Sep 16 2:00s 0 -
+Rule Belgium 1946 only - May 19 2:00s 1:00 S
+Rule Belgium 1946 only - Oct 7 2:00s 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Brussels 0:17:30 - LMT 1880
+ 0:17:30 - BMT 1892 May 1 12:00 # Brussels MT
+ 0:00 - WET 1914 Nov 8
+ 1:00 - CET 1916 May 1 0:00
+ 1:00 C-Eur CE%sT 1918 Nov 11 11:00u
+ 0:00 Belgium WE%sT 1940 May 20 2:00s
+ 1:00 C-Eur CE%sT 1944 Sep 3
+ 1:00 Belgium CE%sT 1977
+ 1:00 EU CE%sT
+
+# Bosnia and Herzegovina
+# see Serbia
+
+# Bulgaria
+#
+# From Plamen Simenov via Steffen Thorsen (1999-09-09):
+# A document of Government of Bulgaria (No.94/1997) says:
+# EET --> EETDST is in 03:00 Local time in last Sunday of March ...
+# EETDST --> EET is in 04:00 Local time in last Sunday of October
+#
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Bulg 1979 only - Mar 31 23:00 1:00 S
+Rule Bulg 1979 only - Oct 1 1:00 0 -
+Rule Bulg 1980 1982 - Apr Sat>=1 23:00 1:00 S
+Rule Bulg 1980 only - Sep 29 1:00 0 -
+Rule Bulg 1981 only - Sep 27 2:00 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Sofia 1:33:16 - LMT 1880
+ 1:56:56 - IMT 1894 Nov 30 # Istanbul MT?
+ 2:00 - EET 1942 Nov 2 3:00
+ 1:00 C-Eur CE%sT 1945
+ 1:00 - CET 1945 Apr 2 3:00
+ 2:00 - EET 1979 Mar 31 23:00
+ 2:00 Bulg EE%sT 1982 Sep 26 2:00
+ 2:00 C-Eur EE%sT 1991
+ 2:00 E-Eur EE%sT 1997
+ 2:00 EU EE%sT
+
+# Croatia
+# see Serbia
+
+# Cyprus
+# Please see the `asia' file for Asia/Nicosia.
+
+# Czech Republic
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Czech 1945 only - Apr 8 2:00s 1:00 S
+Rule Czech 1945 only - Nov 18 2:00s 0 -
+Rule Czech 1946 only - May 6 2:00s 1:00 S
+Rule Czech 1946 1949 - Oct Sun>=1 2:00s 0 -
+Rule Czech 1947 only - Apr 20 2:00s 1:00 S
+Rule Czech 1948 only - Apr 18 2:00s 1:00 S
+Rule Czech 1949 only - Apr 9 2:00s 1:00 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Prague 0:57:44 - LMT 1850
+ 0:57:44 - PMT 1891 Oct # Prague Mean Time
+ 1:00 C-Eur CE%sT 1944 Sep 17 2:00s
+ 1:00 Czech CE%sT 1979
+ 1:00 EU CE%sT
+
+# Denmark, Faroe Islands, and Greenland
+
+# From Jesper Norgaard Welen (2005-04-26):
+# http://www.hum.aau.dk/~poe/tid/tine/DanskTid.htm says that the law
+# [introducing standard time] was in effect from 1894-01-01....
+# The page http://www.retsinfo.dk/_GETDOCI_/ACCN/A18930008330-REGL
+# confirms this, and states that the law was put forth 1893-03-29.
+#
+# The EU treaty with effect from 1973:
+# http://www.retsinfo.dk/_GETDOCI_/ACCN/A19722110030-REGL
+#
+# This provoked a new law from 1974 to make possible summer time changes
+# in subsequenet decrees with the law
+# http://www.retsinfo.dk/_GETDOCI_/ACCN/A19740022330-REGL
+#
+# It seems however that no decree was set forward until 1980. I have
+# not found any decree, but in another related law, the effecting DST
+# changes are stated explicitly to be from 1980-04-06 at 02:00 to
+# 1980-09-28 at 02:00. If this is true, this differs slightly from
+# the EU rule in that DST runs to 02:00, not 03:00. We don't know
+# when Denmark began using the EU rule correctly, but we have only
+# confirmation of the 1980-time, so I presume it was correct in 1981:
+# The law is about the management of the extra hour, concerning
+# working hours reported and effect on obligatory-rest rules (which
+# was suspended on that night):
+# http://www.retsinfo.dk/_GETDOCI_/ACCN/C19801120554-REGL
+
+# From Jesper Norgaard Welen (2005-06-11):
+# The Herning Folkeblad (1980-09-26) reported that the night between
+# Saturday and Sunday the clock is set back from three to two.
+
+# From Paul Eggert (2005-06-11):
+# Hence the "02:00" of the 1980 law refers to standard time, not
+# wall-clock time, and so the EU rules were in effect in 1980.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Denmark 1916 only - May 14 23:00 1:00 S
+Rule Denmark 1916 only - Sep 30 23:00 0 -
+Rule Denmark 1940 only - May 15 0:00 1:00 S
+Rule Denmark 1945 only - Apr 2 2:00s 1:00 S
+Rule Denmark 1945 only - Aug 15 2:00s 0 -
+Rule Denmark 1946 only - May 1 2:00s 1:00 S
+Rule Denmark 1946 only - Sep 1 2:00s 0 -
+Rule Denmark 1947 only - May 4 2:00s 1:00 S
+Rule Denmark 1947 only - Aug 10 2:00s 0 -
+Rule Denmark 1948 only - May 9 2:00s 1:00 S
+Rule Denmark 1948 only - Aug 8 2:00s 0 -
+#
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Copenhagen 0:50:20 - LMT 1890
+ 0:50:20 - CMT 1894 Jan 1 # Copenhagen MT
+ 1:00 Denmark CE%sT 1942 Nov 2 2:00s
+ 1:00 C-Eur CE%sT 1945 Apr 2 2:00
+ 1:00 Denmark CE%sT 1980
+ 1:00 EU CE%sT
+Zone Atlantic/Faroe -0:27:04 - LMT 1908 Jan 11 # Torshavn
+ 0:00 - WET 1981
+ 0:00 EU WE%sT
+#
+# From Paul Eggert (2004-10-31):
+# During World War II, Germany maintained secret manned weather stations in
+# East Greenland and Franz Josef Land, but we don't know their time zones.
+# My source for this is Wilhelm Dege's book mentioned under Svalbard.
+#
+# From Paul Eggert (2006-03-22):
+# Greenland joined the EU as part of Denmark, obtained home rule on 1979-05-01,
+# and left the EU on 1985-02-01. It therefore should have been using EU
+# rules at least through 1984. Shanks & Pottenger say Scoresbysund and Godthab
+# used C-Eur rules after 1980, but IATA SSIM (1991/1996) says they use EU
+# rules since at least 1991. Assume EU rules since 1980.
+
+# From Gwillin Law (2001-06-06), citing
+# <http://www.statkart.no/efs/efshefter/2001/efs5-2001.pdf> (2001-03-15),
+# and with translations corrected by Steffen Thorsen:
+#
+# Greenland has four local times, and the relation to UTC
+# is according to the following time line:
+#
+# The military zone near Thule UTC-4
+# Standard Greenland time UTC-3
+# Scoresbysund UTC-1
+# Danmarkshavn UTC
+#
+# In the military area near Thule and in Danmarkshavn DST will not be
+# introduced.
+
+# From Rives McDow (2001-11-01):
+#
+# I correspond regularly with the Dansk Polarcenter, and wrote them at
+# the time to clarify the situation in Thule. Unfortunately, I have
+# not heard back from them regarding my recent letter. [But I have
+# info from earlier correspondence.]
+#
+# According to the center, a very small local time zone around Thule
+# Air Base keeps the time according to UTC-4, implementing daylight
+# savings using North America rules, changing the time at 02:00 local time....
+#
+# The east coast of Greenland north of the community of Scoresbysund
+# uses UTC in the same way as in Iceland, year round, with no dst.
+# There are just a few stations on this coast, including the
+# Danmarkshavn ICAO weather station mentioned in your September 29th
+# email. The other stations are two sledge patrol stations in
+# Mestersvig and Daneborg, the air force base at Station Nord, and the
+# DPC research station at Zackenberg.
+#
+# Scoresbysund and two small villages nearby keep time UTC-1 and use
+# the same daylight savings time period as in West Greenland (Godthab).
+#
+# The rest of Greenland, including Godthab (this area, although it
+# includes central Greenland, is known as west Greenland), keeps time
+# UTC-3, with daylight savings methods according to European rules.
+#
+# It is common procedure to use UTC 0 in the wilderness of East and
+# North Greenland, because it is mainly Icelandic aircraft operators
+# maintaining traffic in these areas. However, the official status of
+# this area is that it sticks with Godthab time. This area might be
+# considered a dual time zone in some respects because of this.
+
+# From Rives McDow (2001-11-19):
+# I heard back from someone stationed at Thule; the time change took place
+# there at 2:00 AM.
+
+# From Paul Eggert (2006-03-22):
+# From 1997 on the CIA map shows Danmarkshavn on GMT;
+# the 1995 map as like Godthab.
+# For lack of better info, assume they were like Godthab before 1996.
+# startkart.no says Thule does not observe DST, but this is clearly an error,
+# so go with Shanks & Pottenger for Thule transitions until this year.
+# For 2007 on assume Thule will stay in sync with US DST rules.
+#
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Thule 1991 1992 - Mar lastSun 2:00 1:00 D
+Rule Thule 1991 1992 - Sep lastSun 2:00 0 S
+Rule Thule 1993 2006 - Apr Sun>=1 2:00 1:00 D
+Rule Thule 1993 2006 - Oct lastSun 2:00 0 S
+Rule Thule 2007 max - Mar Sun>=8 2:00 1:00 D
+Rule Thule 2007 max - Nov Sun>=1 2:00 0 S
+#
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Danmarkshavn -1:14:40 - LMT 1916 Jul 28
+ -3:00 - WGT 1980 Apr 6 2:00
+ -3:00 EU WG%sT 1996
+ 0:00 - GMT
+Zone America/Scoresbysund -1:27:52 - LMT 1916 Jul 28 # Ittoqqortoormiit
+ -2:00 - CGT 1980 Apr 6 2:00
+ -2:00 C-Eur CG%sT 1981 Mar 29
+ -1:00 EU EG%sT
+Zone America/Godthab -3:26:56 - LMT 1916 Jul 28 # Nuuk
+ -3:00 - WGT 1980 Apr 6 2:00
+ -3:00 EU WG%sT
+Zone America/Thule -4:35:08 - LMT 1916 Jul 28 # Pituffik air base
+ -4:00 Thule A%sT
+
+# Estonia
+# From Peter Ilieve (1994-10-15):
+# A relative in Tallinn confirms the accuracy of the data for 1989 onwards
+# [through 1994] and gives the legal authority for it,
+# a regulation of the Government of Estonia, No. 111 of 1989....
+#
+# From Peter Ilieve (1996-10-28):
+# [IATA SSIM (1992/1996) claims that the Baltic republics switch at 01:00s,
+# but a relative confirms that Estonia still switches at 02:00s, writing:]
+# ``I do not [know] exactly but there are some little different
+# (confusing) rules for International Air and Railway Transport Schedules
+# conversion in Sunday connected with end of summer time in Estonia....
+# A discussion is running about the summer time efficiency and effect on
+# human physiology. It seems that Estonia maybe will not change to
+# summer time next spring.''
+
+# From Peter Ilieve (1998-11-04), heavily edited:
+# <a href="http://trip.rk.ee/cgi-bin/thw?${BASE}=akt&${OOHTML}=rtd&TA=1998&TO=1&AN=1390">
+# The 1998-09-22 Estonian time law
+# </a>
+# refers to the Eighth Directive and cites the association agreement between
+# the EU and Estonia, ratified by the Estonian law (RT II 1995, 22--27, 120).
+#
+# I also asked [my relative] whether they use any standard abbreviation
+# for their standard and summer times. He says no, they use "suveaeg"
+# (summer time) and "talveaeg" (winter time).
+
+# From <a href="http://www.baltictimes.com/">The Baltic Times</a> (1999-09-09)
+# via Steffen Thorsen:
+# This year will mark the last time Estonia shifts to summer time,
+# a council of the ruling coalition announced Sept. 6....
+# But what this could mean for Estonia's chances of joining the European
+# Union are still unclear. In 1994, the EU declared summer time compulsory
+# for all member states until 2001. Brussels has yet to decide what to do
+# after that.
+
+# From Mart Oruaas (2000-01-29):
+# Regulation no. 301 (1999-10-12) obsoletes previous regulation
+# no. 206 (1998-09-22) and thus sticks Estonia to +02:00 GMT for all
+# the year round. The regulation is effective 1999-11-01.
+
+# From Toomas Soome (2002-02-21):
+# The Estonian government has changed once again timezone politics.
+# Now we are using again EU rules.
+#
+# From Urmet Jaanes (2002-03-28):
+# The legislative reference is Government decree No. 84 on 2002-02-21.
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Tallinn 1:39:00 - LMT 1880
+ 1:39:00 - TMT 1918 Feb # Tallinn Mean Time
+ 1:00 C-Eur CE%sT 1919 Jul
+ 1:39:00 - TMT 1921 May
+ 2:00 - EET 1940 Aug 6
+ 3:00 - MSK 1941 Sep 15
+ 1:00 C-Eur CE%sT 1944 Sep 22
+ 3:00 Russia MSK/MSD 1989 Mar 26 2:00s
+ 2:00 1:00 EEST 1989 Sep 24 2:00s
+ 2:00 C-Eur EE%sT 1998 Sep 22
+ 2:00 EU EE%sT 1999 Nov 1
+ 2:00 - EET 2002 Feb 21
+ 2:00 EU EE%sT
+
+# Finland
+#
+# From Hannu Strang (1994-09-25 06:03:37 UTC):
+# Well, here in Helsinki we're just changing from summer time to regular one,
+# and it's supposed to change at 4am...
+#
+# From Paul Eggert (2006-03-22):
+# Shanks & Pottenger say Finland has switched at 02:00 standard time
+# since 1981. Go with Strang instead.
+#
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Finland 1942 only - Apr 3 0:00 1:00 S
+Rule Finland 1942 only - Oct 3 0:00 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Helsinki 1:39:52 - LMT 1878 May 31
+ 1:39:52 - HMT 1921 May # Helsinki Mean Time
+ 2:00 Finland EE%sT 1981 Mar 29 2:00
+ 2:00 EU EE%sT
+
+# Aaland Is
+Link Europe/Helsinki Europe/Mariehamn
+
+
+# France
+
+# From Ciro Discepolo (2000-12-20):
+#
+# Henri Le Corre, Regimes Horaires pour le monde entier, Editions
+# Traditionnelles - Paris 2 books, 1993
+#
+# Gabriel, Traite de l'heure dans le monde, Guy Tredaniel editeur,
+# Paris, 1991
+#
+# Francoise Gauquelin, Problemes de l'heure resolus en astrologie,
+# Guy tredaniel, Paris 1987
+
+
+#
+# Shank & Pottenger seem to use `24:00' ambiguously; resolve it with Whitman.
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule France 1916 only - Jun 14 23:00s 1:00 S
+Rule France 1916 1919 - Oct Sun>=1 23:00s 0 -
+Rule France 1917 only - Mar 24 23:00s 1:00 S
+Rule France 1918 only - Mar 9 23:00s 1:00 S
+Rule France 1919 only - Mar 1 23:00s 1:00 S
+Rule France 1920 only - Feb 14 23:00s 1:00 S
+Rule France 1920 only - Oct 23 23:00s 0 -
+Rule France 1921 only - Mar 14 23:00s 1:00 S
+Rule France 1921 only - Oct 25 23:00s 0 -
+Rule France 1922 only - Mar 25 23:00s 1:00 S
+# DSH writes that a law of 1923-05-24 specified 3rd Sat in Apr at 23:00 to 1st
+# Sat in Oct at 24:00; and that in 1930, because of Easter, the transitions
+# were Apr 12 and Oct 5. Go with Shanks & Pottenger.
+Rule France 1922 1938 - Oct Sat>=1 23:00s 0 -
+Rule France 1923 only - May 26 23:00s 1:00 S
+Rule France 1924 only - Mar 29 23:00s 1:00 S
+Rule France 1925 only - Apr 4 23:00s 1:00 S
+Rule France 1926 only - Apr 17 23:00s 1:00 S
+Rule France 1927 only - Apr 9 23:00s 1:00 S
+Rule France 1928 only - Apr 14 23:00s 1:00 S
+Rule France 1929 only - Apr 20 23:00s 1:00 S
+Rule France 1930 only - Apr 12 23:00s 1:00 S
+Rule France 1931 only - Apr 18 23:00s 1:00 S
+Rule France 1932 only - Apr 2 23:00s 1:00 S
+Rule France 1933 only - Mar 25 23:00s 1:00 S
+Rule France 1934 only - Apr 7 23:00s 1:00 S
+Rule France 1935 only - Mar 30 23:00s 1:00 S
+Rule France 1936 only - Apr 18 23:00s 1:00 S
+Rule France 1937 only - Apr 3 23:00s 1:00 S
+Rule France 1938 only - Mar 26 23:00s 1:00 S
+Rule France 1939 only - Apr 15 23:00s 1:00 S
+Rule France 1939 only - Nov 18 23:00s 0 -
+Rule France 1940 only - Feb 25 2:00 1:00 S
+# The French rules for 1941-1944 were not used in Paris, but Shanks & Pottenger
+# write that they were used in Monaco and in many French locations.
+# Le Corre writes that the upper limit of the free zone was Arneguy, Orthez,
+# Mont-de-Marsan, Bazas, Langon, Lamotte-Montravel, Marouil, La
+# Rochefoucault, Champagne-Mouton, La Roche-Posay, La Haye-Decartes,
+# Loches, Montrichard, Vierzon, Bourges, Moulins, Digoin,
+# Paray-le-Monial, Montceau-les-Mines, Chalons-sur-Saone, Arbois,
+# Dole, Morez, St-Claude, and Collognes (Haute-Savioe).
+Rule France 1941 only - May 5 0:00 2:00 M # Midsummer
+# Shanks & Pottenger say this transition occurred at Oct 6 1:00,
+# but go with Denis Excoffier (1997-12-12),
+# who quotes the Ephemerides Astronomiques for 1998 from Bureau des Longitudes
+# as saying 5/10/41 22hUT.
+Rule France 1941 only - Oct 6 0:00 1:00 S
+Rule France 1942 only - Mar 9 0:00 2:00 M
+Rule France 1942 only - Nov 2 3:00 1:00 S
+Rule France 1943 only - Mar 29 2:00 2:00 M
+Rule France 1943 only - Oct 4 3:00 1:00 S
+Rule France 1944 only - Apr 3 2:00 2:00 M
+Rule France 1944 only - Oct 8 1:00 1:00 S
+Rule France 1945 only - Apr 2 2:00 2:00 M
+Rule France 1945 only - Sep 16 3:00 0 -
+# Shanks & Pottenger give Mar 28 2:00 and Sep 26 3:00;
+# go with Excoffier's 28/3/76 0hUT and 25/9/76 23hUT.
+Rule France 1976 only - Mar 28 1:00 1:00 S
+Rule France 1976 only - Sep 26 1:00 0 -
+# Shanks & Pottenger give 0:09:20 for Paris Mean Time, and Whitman 0:09:05,
+# but Howse quotes the actual French legislation as saying 0:09:21.
+# Go with Howse. Howse writes that the time in France was officially based
+# on PMT-0:09:21 until 1978-08-09, when the time base finally switched to UTC.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Paris 0:09:21 - LMT 1891 Mar 15 0:01
+ 0:09:21 - PMT 1911 Mar 11 0:01 # Paris MT
+# Shanks & Pottenger give 1940 Jun 14 0:00; go with Excoffier and Le Corre.
+ 0:00 France WE%sT 1940 Jun 14 23:00
+# Le Corre says Paris stuck with occupied-France time after the liberation;
+# go with Shanks & Pottenger.
+ 1:00 C-Eur CE%sT 1944 Aug 25
+ 0:00 France WE%sT 1945 Sep 16 3:00
+ 1:00 France CE%sT 1977
+ 1:00 EU CE%sT
+
+# Germany
+
+# From Markus Kuhn (1998-09-29):
+# The German time zone web site by the Physikalisch-Technische
+# Bundesanstalt contains DST information back to 1916.
+# [See tz-link.htm for the URL.]
+
+# From Joerg Schilling (2002-10-23):
+# In 1945, Berlin was switched to Moscow Summer time (GMT+4) by
+# <a href="http://www.dhm.de/lemo/html/biografien/BersarinNikolai/">
+# General [Nikolai] Bersarin</a>.
+
+# From Paul Eggert (2003-03-08):
+# <a href="http://www.parlament-berlin.de/pds-fraktion.nsf/727459127c8b66ee8525662300459099/defc77cb784f180ac1256c2b0030274b/$FILE/bersarint.pdf">
+# http://www.parlament-berlin.de/pds-fraktion.nsf/727459127c8b66ee8525662300459099/defc77cb784f180ac1256c2b0030274b/$FILE/bersarint.pdf
+# </a>
+# says that Bersarin issued an order to use Moscow time on May 20.
+# However, Moscow did not observe daylight saving in 1945, so
+# this was equivalent to CEMT (GMT+3), not GMT+4.
+
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Germany 1946 only - Apr 14 2:00s 1:00 S
+Rule Germany 1946 only - Oct 7 2:00s 0 -
+Rule Germany 1947 1949 - Oct Sun>=1 2:00s 0 -
+# http://www.ptb.de/de/org/4/44/441/salt.htm says the following transition
+# occurred at 3:00 MEZ, not the 2:00 MEZ given in Shanks & Pottenger.
+# Go with the PTB.
+Rule Germany 1947 only - Apr 6 3:00s 1:00 S
+Rule Germany 1947 only - May 11 2:00s 2:00 M
+Rule Germany 1947 only - Jun 29 3:00 1:00 S
+Rule Germany 1948 only - Apr 18 2:00s 1:00 S
+Rule Germany 1949 only - Apr 10 2:00s 1:00 S
+
+Rule SovietZone 1945 only - May 24 2:00 2:00 M # Midsummer
+Rule SovietZone 1945 only - Sep 24 3:00 1:00 S
+Rule SovietZone 1945 only - Nov 18 2:00s 0 -
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Berlin 0:53:28 - LMT 1893 Apr
+ 1:00 C-Eur CE%sT 1945 May 24 2:00
+ 1:00 SovietZone CE%sT 1946
+ 1:00 Germany CE%sT 1980
+ 1:00 EU CE%sT
+
+# Georgia
+# Please see the "asia" file for Asia/Tbilisi.
+# Herodotus (Histories, IV.45) says Georgia north of the Phasis (now Rioni)
+# is in Europe. Our reference location Tbilisi is in the Asian part.
+
+# Gibraltar
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Gibraltar -0:21:24 - LMT 1880 Aug 2 0:00s
+ 0:00 GB-Eire %s 1957 Apr 14 2:00
+ 1:00 - CET 1982
+ 1:00 EU CE%sT
+
+# Greece
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+# Whitman gives 1932 Jul 5 - Nov 1; go with Shanks & Pottenger.
+Rule Greece 1932 only - Jul 7 0:00 1:00 S
+Rule Greece 1932 only - Sep 1 0:00 0 -
+# Whitman gives 1941 Apr 25 - ?; go with Shanks & Pottenger.
+Rule Greece 1941 only - Apr 7 0:00 1:00 S
+# Whitman gives 1942 Feb 2 - ?; go with Shanks & Pottenger.
+Rule Greece 1942 only - Nov 2 3:00 0 -
+Rule Greece 1943 only - Mar 30 0:00 1:00 S
+Rule Greece 1943 only - Oct 4 0:00 0 -
+# Whitman gives 1944 Oct 3 - Oct 31; go with Shanks & Pottenger.
+Rule Greece 1952 only - Jul 1 0:00 1:00 S
+Rule Greece 1952 only - Nov 2 0:00 0 -
+Rule Greece 1975 only - Apr 12 0:00s 1:00 S
+Rule Greece 1975 only - Nov 26 0:00s 0 -
+Rule Greece 1976 only - Apr 11 2:00s 1:00 S
+Rule Greece 1976 only - Oct 10 2:00s 0 -
+Rule Greece 1977 1978 - Apr Sun>=1 2:00s 1:00 S
+Rule Greece 1977 only - Sep 26 2:00s 0 -
+Rule Greece 1978 only - Sep 24 4:00 0 -
+Rule Greece 1979 only - Apr 1 9:00 1:00 S
+Rule Greece 1979 only - Sep 29 2:00 0 -
+Rule Greece 1980 only - Apr 1 0:00 1:00 S
+Rule Greece 1980 only - Sep 28 0:00 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Athens 1:34:52 - LMT 1895 Sep 14
+ 1:34:52 - AMT 1916 Jul 28 0:01 # Athens MT
+ 2:00 Greece EE%sT 1941 Apr 30
+ 1:00 Greece CE%sT 1944 Apr 4
+ 2:00 Greece EE%sT 1981
+ # Shanks & Pottenger say it switched to C-Eur in 1981;
+ # go with EU instead, since Greece joined it on Jan 1.
+ 2:00 EU EE%sT
+
+# Hungary
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Hungary 1918 only - Apr 1 3:00 1:00 S
+Rule Hungary 1918 only - Sep 29 3:00 0 -
+Rule Hungary 1919 only - Apr 15 3:00 1:00 S
+Rule Hungary 1919 only - Sep 15 3:00 0 -
+Rule Hungary 1920 only - Apr 5 3:00 1:00 S
+Rule Hungary 1920 only - Sep 30 3:00 0 -
+Rule Hungary 1945 only - May 1 23:00 1:00 S
+Rule Hungary 1945 only - Nov 3 0:00 0 -
+Rule Hungary 1946 only - Mar 31 2:00s 1:00 S
+Rule Hungary 1946 1949 - Oct Sun>=1 2:00s 0 -
+Rule Hungary 1947 1949 - Apr Sun>=4 2:00s 1:00 S
+Rule Hungary 1950 only - Apr 17 2:00s 1:00 S
+Rule Hungary 1950 only - Oct 23 2:00s 0 -
+Rule Hungary 1954 1955 - May 23 0:00 1:00 S
+Rule Hungary 1954 1955 - Oct 3 0:00 0 -
+Rule Hungary 1956 only - Jun Sun>=1 0:00 1:00 S
+Rule Hungary 1956 only - Sep lastSun 0:00 0 -
+Rule Hungary 1957 only - Jun Sun>=1 1:00 1:00 S
+Rule Hungary 1957 only - Sep lastSun 3:00 0 -
+Rule Hungary 1980 only - Apr 6 1:00 1:00 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Budapest 1:16:20 - LMT 1890 Oct
+ 1:00 C-Eur CE%sT 1918
+ 1:00 Hungary CE%sT 1941 Apr 6 2:00
+ 1:00 C-Eur CE%sT 1945
+ 1:00 Hungary CE%sT 1980 Sep 28 2:00s
+ 1:00 EU CE%sT
+
+# Iceland
+#
+# From Adam David (1993-11-06):
+# The name of the timezone in Iceland for system / mail / news purposes is GMT.
+#
+# (1993-12-05):
+# This material is paraphrased from the 1988 edition of the University of
+# Iceland Almanak.
+#
+# From January 1st, 1908 the whole of Iceland was standardised at 1 hour
+# behind GMT. Previously, local mean solar time was used in different parts
+# of Iceland, the almanak had been based on Reykjavik mean solar time which
+# was 1 hour and 28 minutes behind GMT.
+#
+# "first day of winter" referred to [below] means the first day of the 26 weeks
+# of winter, according to the old icelandic calendar that dates back to the
+# time the norsemen first settled Iceland. The first day of winter is always
+# Saturday, but is not dependent on the Julian or Gregorian calendars.
+#
+# (1993-12-10):
+# I have a reference from the Oxford Icelandic-English dictionary for the
+# beginning of winter, which ties it to the ecclesiastical calendar (and thus
+# to the julian/gregorian calendar) over the period in question.
+# the winter begins on the Saturday next before St. Luke's day
+# (old style), or on St. Luke's day, if a Saturday.
+# St. Luke's day ought to be traceable from ecclesiastical sources. "old style"
+# might be a reference to the Julian calendar as opposed to Gregorian, or it
+# might mean something else (???).
+#
+# From Paul Eggert (2006-03-22):
+# The Iceland Almanak, Shanks & Pottenger, and Whitman disagree on many points.
+# We go with the Almanak, except for one claim from Shanks & Pottenger, namely
+# that Reykavik was 21W57 from 1837 to 1908, local mean time before that.
+#
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Iceland 1917 1918 - Feb 19 23:00 1:00 S
+Rule Iceland 1917 only - Oct 21 1:00 0 -
+Rule Iceland 1918 only - Nov 16 1:00 0 -
+Rule Iceland 1939 only - Apr 29 23:00 1:00 S
+Rule Iceland 1939 only - Nov 29 2:00 0 -
+Rule Iceland 1940 only - Feb 25 2:00 1:00 S
+Rule Iceland 1940 only - Nov 3 2:00 0 -
+Rule Iceland 1941 only - Mar 2 1:00s 1:00 S
+Rule Iceland 1941 only - Nov 2 1:00s 0 -
+Rule Iceland 1942 only - Mar 8 1:00s 1:00 S
+Rule Iceland 1942 only - Oct 25 1:00s 0 -
+# 1943-1946 - first Sunday in March until first Sunday in winter
+Rule Iceland 1943 1946 - Mar Sun>=1 1:00s 1:00 S
+Rule Iceland 1943 1948 - Oct Sun>=22 1:00s 0 -
+# 1947-1967 - first Sunday in April until first Sunday in winter
+Rule Iceland 1947 1967 - Apr Sun>=1 1:00s 1:00 S
+# 1949 Oct transition delayed by 1 week
+Rule Iceland 1949 only - Oct 30 1:00s 0 -
+Rule Iceland 1950 1966 - Oct Sun>=22 1:00s 0 -
+Rule Iceland 1967 only - Oct 29 1:00s 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Atlantic/Reykjavik -1:27:24 - LMT 1837
+ -1:27:48 - RMT 1908 # Reykjavik Mean Time?
+ -1:00 Iceland IS%sT 1968 Apr 7 1:00s
+ 0:00 - GMT
+
+# Italy
+#
+# From Paul Eggert (2001-03-06):
+# Sicily and Sardinia each had their own time zones from 1866 to 1893,
+# called Palermo Time (+00:53:28) and Cagliari Time (+00:36:32).
+# During World War II, German-controlled Italy used German time.
+# But these events all occurred before the 1970 cutoff,
+# so record only the time in Rome.
+#
+# From Paul Eggert (2006-03-22):
+# For Italian DST we have three sources: Shanks & Pottenger, Whitman, and
+# F. Pollastri
+# <a href="http://toi.iriti.cnr.it/uk/ienitlt.html">
+# Day-light Saving Time in Italy (2006-02-03)
+# </a>
+# (`FP' below), taken from an Italian National Electrotechnical Institute
+# publication. When the three sources disagree, guess who's right, as follows:
+#
+# year FP Shanks&P. (S) Whitman (W) Go with:
+# 1916 06-03 06-03 24:00 06-03 00:00 FP & W
+# 09-30 09-30 24:00 09-30 01:00 FP; guess 24:00s
+# 1917 04-01 03-31 24:00 03-31 00:00 FP & S
+# 09-30 09-29 24:00 09-30 01:00 FP & W
+# 1918 03-09 03-09 24:00 03-09 00:00 FP & S
+# 10-06 10-05 24:00 10-06 01:00 FP & W
+# 1919 03-01 03-01 24:00 03-01 00:00 FP & S
+# 10-04 10-04 24:00 10-04 01:00 FP; guess 24:00s
+# 1920 03-20 03-20 24:00 03-20 00:00 FP & S
+# 09-18 09-18 24:00 10-01 01:00 FP; guess 24:00s
+# 1944 04-02 04-03 02:00 S (see C-Eur)
+# 09-16 10-02 03:00 FP; guess 24:00s
+# 1945 09-14 09-16 24:00 FP; guess 24:00s
+# 1970 05-21 05-31 00:00 S
+# 09-20 09-27 00:00 S
+#
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Italy 1916 only - Jun 3 0:00s 1:00 S
+Rule Italy 1916 only - Oct 1 0:00s 0 -
+Rule Italy 1917 only - Apr 1 0:00s 1:00 S
+Rule Italy 1917 only - Sep 30 0:00s 0 -
+Rule Italy 1918 only - Mar 10 0:00s 1:00 S
+Rule Italy 1918 1919 - Oct Sun>=1 0:00s 0 -
+Rule Italy 1919 only - Mar 2 0:00s 1:00 S
+Rule Italy 1920 only - Mar 21 0:00s 1:00 S
+Rule Italy 1920 only - Sep 19 0:00s 0 -
+Rule Italy 1940 only - Jun 15 0:00s 1:00 S
+Rule Italy 1944 only - Sep 17 0:00s 0 -
+Rule Italy 1945 only - Apr 2 2:00 1:00 S
+Rule Italy 1945 only - Sep 15 0:00s 0 -
+Rule Italy 1946 only - Mar 17 2:00s 1:00 S
+Rule Italy 1946 only - Oct 6 2:00s 0 -
+Rule Italy 1947 only - Mar 16 0:00s 1:00 S
+Rule Italy 1947 only - Oct 5 0:00s 0 -
+Rule Italy 1948 only - Feb 29 2:00s 1:00 S
+Rule Italy 1948 only - Oct 3 2:00s 0 -
+Rule Italy 1966 1968 - May Sun>=22 0:00 1:00 S
+Rule Italy 1966 1969 - Sep Sun>=22 0:00 0 -
+Rule Italy 1969 only - Jun 1 0:00 1:00 S
+Rule Italy 1970 only - May 31 0:00 1:00 S
+Rule Italy 1970 only - Sep lastSun 0:00 0 -
+Rule Italy 1971 1972 - May Sun>=22 0:00 1:00 S
+Rule Italy 1971 only - Sep lastSun 1:00 0 -
+Rule Italy 1972 only - Oct 1 0:00 0 -
+Rule Italy 1973 only - Jun 3 0:00 1:00 S
+Rule Italy 1973 1974 - Sep lastSun 0:00 0 -
+Rule Italy 1974 only - May 26 0:00 1:00 S
+Rule Italy 1975 only - Jun 1 0:00s 1:00 S
+Rule Italy 1975 1977 - Sep lastSun 0:00s 0 -
+Rule Italy 1976 only - May 30 0:00s 1:00 S
+Rule Italy 1977 1979 - May Sun>=22 0:00s 1:00 S
+Rule Italy 1978 only - Oct 1 0:00s 0 -
+Rule Italy 1979 only - Sep 30 0:00s 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Rome 0:49:56 - LMT 1866 Sep 22
+ 0:49:56 - RMT 1893 Nov 1 0:00s # Rome Mean
+ 1:00 Italy CE%sT 1942 Nov 2 2:00s
+ 1:00 C-Eur CE%sT 1944 Jul
+ 1:00 Italy CE%sT 1980
+ 1:00 EU CE%sT
+
+Link Europe/Rome Europe/Vatican
+Link Europe/Rome Europe/San_Marino
+
+# Latvia
+
+# From Liene Kanepe (1998-09-17):
+
+# I asked about this matter Scientific Secretary of the Institute of Astronomy
+# of The University of Latvia Dr. paed Mr. Ilgonis Vilks. I also searched the
+# correct data in juridical acts and I found some juridical documents about
+# changes in the counting of time in Latvia from 1981....
+#
+# Act No.35 of the Council of Ministers of Latvian SSR of 1981-01-22 ...
+# according to the Act No.925 of the Council of Ministers of USSR of 1980-10-24
+# ...: all year round the time of 2nd time zone + 1 hour, in addition turning
+# the hands of the clock 1 hour forward on 1 April at 00:00 (GMT 31 March 21:00)
+# and 1 hour backward on the 1 October at 00:00 (GMT 30 September 20:00).
+#
+# Act No.592 of the Council of Ministers of Latvian SSR of 1984-09-24 ...
+# according to the Act No.967 of the Council of Ministers of USSR of 1984-09-13
+# ...: all year round the time of 2nd time zone + 1 hour, in addition turning
+# the hands of the clock 1 hour forward on the last Sunday of March at 02:00
+# (GMT 23:00 on the previous day) and 1 hour backward on the last Sunday of
+# September at 03:00 (GMT 23:00 on the previous day).
+#
+# Act No.81 of the Council of Ministers of Latvian SSR of 1989-03-22 ...
+# according to the Act No.227 of the Council of Ministers of USSR of 1989-03-14
+# ...: since the last Sunday of March 1989 in Lithuanian SSR, Latvian SSR,
+# Estonian SSR and Kaliningrad region of Russian Federation all year round the
+# time of 2nd time zone (Moscow time minus one hour). On the territory of Latvia
+# transition to summer time is performed on the last Sunday of March at 02:00
+# (GMT 00:00), turning the hands of the clock 1 hour forward. The end of
+# daylight saving time is performed on the last Sunday of September at 03:00
+# (GMT 00:00), turning the hands of the clock 1 hour backward. Exception is
+# 1989-03-26, when we must not turn the hands of the clock....
+#
+# The Regulations of the Cabinet of Ministers of the Republic of Latvia of
+# 1997-01-21 on transition to Summer time ... established the same order of
+# daylight savings time settings as in the States of the European Union.
+
+# From Andrei Ivanov (2000-03-06):
+# This year Latvia will not switch to Daylight Savings Time (as specified in
+# <a href="http://www.lv-laiks.lv/wwwraksti/2000/071072/vd4.htm">
+# The Regulations of the Cabinet of Ministers of the Rep. of Latvia of
+# 29-Feb-2000 (#79)</a>, in Latvian for subscribers only).
+
+# <a href="http://www.rferl.org/newsline/2001/01/3-CEE/cee-030101.html">
+# From RFE/RL Newsline (2001-01-03), noted after a heads-up by Rives McDow:
+# </a>
+# The Latvian government on 2 January decided that the country will
+# institute daylight-saving time this spring, LETA reported.
+# Last February the three Baltic states decided not to turn back their
+# clocks one hour in the spring....
+# Minister of Economy Aigars Kalvitis noted that Latvia had too few
+# daylight hours and thus decided to comply with a draft European
+# Commission directive that provides for instituting daylight-saving
+# time in EU countries between 2002 and 2006. The Latvian government
+# urged Lithuania and Estonia to adopt a similar time policy, but it
+# appears that they will not do so....
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Latvia 1989 1996 - Mar lastSun 2:00s 1:00 S
+Rule Latvia 1989 1996 - Sep lastSun 2:00s 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Riga 1:36:24 - LMT 1880
+ 1:36:24 - RMT 1918 Apr 15 2:00 #Riga Mean Time
+ 1:36:24 1:00 LST 1918 Sep 16 3:00 #Latvian Summer
+ 1:36:24 - RMT 1919 Apr 1 2:00
+ 1:36:24 1:00 LST 1919 May 22 3:00
+ 1:36:24 - RMT 1926 May 11
+ 2:00 - EET 1940 Aug 5
+ 3:00 - MSK 1941 Jul
+ 1:00 C-Eur CE%sT 1944 Oct 13
+ 3:00 Russia MSK/MSD 1989 Mar lastSun 2:00s
+ 2:00 1:00 EEST 1989 Sep lastSun 2:00s
+ 2:00 Latvia EE%sT 1997 Jan 21
+ 2:00 EU EE%sT 2000 Feb 29
+ 2:00 - EET 2001 Jan 2
+ 2:00 EU EE%sT
+
+# Liechtenstein
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Vaduz 0:38:04 - LMT 1894 Jun
+ 1:00 - CET 1981
+ 1:00 EU CE%sT
+
+# Lithuania
+
+# From Paul Eggert (1996-11-22):
+# IATA SSIM (1992/1996) says Lithuania uses W-Eur rules, but since it is
+# known to be wrong about Estonia and Latvia, assume it's wrong here too.
+
+# From Marius Gedminas (1998-08-07):
+# I would like to inform that in this year Lithuanian time zone
+# (Europe/Vilnius) was changed.
+
+# From <a href="http://www.elta.lt/">ELTA</a> No. 972 (2582) (1999-09-29),
+# via Steffen Thorsen:
+# Lithuania has shifted back to the second time zone (GMT plus two hours)
+# to be valid here starting from October 31,
+# as decided by the national government on Wednesday....
+# The Lithuanian government also announced plans to consider a
+# motion to give up shifting to summer time in spring, as it was
+# already done by Estonia.
+
+# From the <a href="http://www.tourism.lt/informa/ff.htm">
+# Fact File, Lithuanian State Department of Tourism
+# </a> (2000-03-27): Local time is GMT+2 hours ..., no daylight saving.
+
+# From a user via Klaus Marten (2003-02-07):
+# As a candidate for membership of the European Union, Lithuania will
+# observe Summer Time in 2003, changing its clocks at the times laid
+# down in EU Directive 2000/84 of 19.I.01 (i.e. at the same times as its
+# neighbour Latvia). The text of the Lithuanian government Order of
+# 7.XI.02 to this effect can be found at
+# http://www.lrvk.lt/nut/11/n1749.htm
+
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Vilnius 1:41:16 - LMT 1880
+ 1:24:00 - WMT 1917 # Warsaw Mean Time
+ 1:35:36 - KMT 1919 Oct 10 # Kaunas Mean Time
+ 1:00 - CET 1920 Jul 12
+ 2:00 - EET 1920 Oct 9
+ 1:00 - CET 1940 Aug 3
+ 3:00 - MSK 1941 Jun 24
+ 1:00 C-Eur CE%sT 1944 Aug
+ 3:00 Russia MSK/MSD 1991 Mar 31 2:00s
+ 2:00 1:00 EEST 1991 Sep 29 2:00s
+ 2:00 C-Eur EE%sT 1998
+ 2:00 - EET 1998 Mar 29 1:00u
+ 1:00 EU CE%sT 1999 Oct 31 1:00u
+ 2:00 - EET 2003 Jan 1
+ 2:00 EU EE%sT
+
+# Luxembourg
+# Whitman disagrees with most of these dates in minor ways;
+# go with Shanks & Pottenger.
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Lux 1916 only - May 14 23:00 1:00 S
+Rule Lux 1916 only - Oct 1 1:00 0 -
+Rule Lux 1917 only - Apr 28 23:00 1:00 S
+Rule Lux 1917 only - Sep 17 1:00 0 -
+Rule Lux 1918 only - Apr Mon>=15 2:00s 1:00 S
+Rule Lux 1918 only - Sep Mon>=15 2:00s 0 -
+Rule Lux 1919 only - Mar 1 23:00 1:00 S
+Rule Lux 1919 only - Oct 5 3:00 0 -
+Rule Lux 1920 only - Feb 14 23:00 1:00 S
+Rule Lux 1920 only - Oct 24 2:00 0 -
+Rule Lux 1921 only - Mar 14 23:00 1:00 S
+Rule Lux 1921 only - Oct 26 2:00 0 -
+Rule Lux 1922 only - Mar 25 23:00 1:00 S
+Rule Lux 1922 only - Oct Sun>=2 1:00 0 -
+Rule Lux 1923 only - Apr 21 23:00 1:00 S
+Rule Lux 1923 only - Oct Sun>=2 2:00 0 -
+Rule Lux 1924 only - Mar 29 23:00 1:00 S
+Rule Lux 1924 1928 - Oct Sun>=2 1:00 0 -
+Rule Lux 1925 only - Apr 5 23:00 1:00 S
+Rule Lux 1926 only - Apr 17 23:00 1:00 S
+Rule Lux 1927 only - Apr 9 23:00 1:00 S
+Rule Lux 1928 only - Apr 14 23:00 1:00 S
+Rule Lux 1929 only - Apr 20 23:00 1:00 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Luxembourg 0:24:36 - LMT 1904 Jun
+ 1:00 Lux CE%sT 1918 Nov 25
+ 0:00 Lux WE%sT 1929 Oct 6 2:00s
+ 0:00 Belgium WE%sT 1940 May 14 3:00
+ 1:00 C-Eur WE%sT 1944 Sep 18 3:00
+ 1:00 Belgium CE%sT 1977
+ 1:00 EU CE%sT
+
+# Macedonia
+# see Serbia
+
+# Malta
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Malta 1973 only - Mar 31 0:00s 1:00 S
+Rule Malta 1973 only - Sep 29 0:00s 0 -
+Rule Malta 1974 only - Apr 21 0:00s 1:00 S
+Rule Malta 1974 only - Sep 16 0:00s 0 -
+Rule Malta 1975 1979 - Apr Sun>=15 2:00 1:00 S
+Rule Malta 1975 1980 - Sep Sun>=15 2:00 0 -
+Rule Malta 1980 only - Mar 31 2:00 1:00 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Malta 0:58:04 - LMT 1893 Nov 2 0:00s # Valletta
+ 1:00 Italy CE%sT 1942 Nov 2 2:00s
+ 1:00 C-Eur CE%sT 1945 Apr 2 2:00s
+ 1:00 Italy CE%sT 1973 Mar 31
+ 1:00 Malta CE%sT 1981
+ 1:00 EU CE%sT
+
+# Moldova
+
+# From Paul Eggert (2006-03-22):
+# A previous version of this database followed Shanks & Pottenger, who write
+# that Tiraspol switched to Moscow time on 1992-01-19 at 02:00.
+# However, this is most likely an error, as Moldova declared independence
+# on 1991-08-27 (the 1992-01-19 date is that of a Russian decree).
+# In early 1992 there was large-scale interethnic violence in the area
+# and it's possible that some Russophones continued to observe Moscow time.
+# But [two people] separately reported via
+# Jesper Norgaard that as of 2001-01-24 Tiraspol was like Chisinau.
+# The Tiraspol entry has therefore been removed for now.
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Chisinau 1:55:20 - LMT 1880
+ 1:55 - CMT 1918 Feb 15 # Chisinau MT
+ 1:44:24 - BMT 1931 Jul 24 # Bucharest MT
+ 2:00 Romania EE%sT 1940 Aug 15
+ 2:00 1:00 EEST 1941 Jul 17
+ 1:00 C-Eur CE%sT 1944 Aug 24
+ 3:00 Russia MSK/MSD 1990
+ 3:00 - MSK 1990 May 6
+ 2:00 - EET 1991
+ 2:00 Russia EE%sT 1992
+ 2:00 E-Eur EE%sT 1997
+# See Romania commentary for the guessed 1997 transition to EU rules.
+ 2:00 EU EE%sT
+
+# Monaco
+# Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's
+# more precise 0:09:21.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Monaco 0:29:32 - LMT 1891 Mar 15
+ 0:09:21 - PMT 1911 Mar 11 # Paris Mean Time
+ 0:00 France WE%sT 1945 Sep 16 3:00
+ 1:00 France CE%sT 1977
+ 1:00 EU CE%sT
+
+# Montenegro
+# see Serbia
+
+# Netherlands
+
+# Howse writes that the Netherlands' railways used GMT between 1892 and 1940,
+# but for other purposes the Netherlands used Amsterdam mean time.
+
+# However, Robert H. van Gent writes (2001-04-01):
+# Howse's statement is only correct up to 1909. From 1909-05-01 (00:00:00
+# Amsterdam mean time) onwards, the whole of the Netherlands (including
+# the Dutch railways) was required by law to observe Amsterdam mean time
+# (19 minutes 32.13 seconds ahead of GMT). This had already been the
+# common practice (except for the railways) for many decades but it was
+# not until 1909 when the Dutch government finally defined this by law.
+# On 1937-07-01 this was changed to 20 minutes (exactly) ahead of GMT and
+# was generally known as Dutch Time ("Nederlandse Tijd").
+#
+# (2001-04-08):
+# 1892-05-01 was the date when the Dutch railways were by law required to
+# observe GMT while the remainder of the Netherlands adhered to the common
+# practice of following Amsterdam mean time.
+#
+# (2001-04-09):
+# In 1835 the authorities of the province of North Holland requested the
+# municipal authorities of the towns and cities in the province to observe
+# Amsterdam mean time but I do not know in how many cases this request was
+# actually followed.
+#
+# From 1852 onwards the Dutch telegraph offices were by law required to
+# observe Amsterdam mean time. As the time signals from the observatory of
+# Leiden were also distributed by the telegraph system, I assume that most
+# places linked up with the telegraph (and railway) system automatically
+# adopted Amsterdam mean time.
+#
+# Although the early Dutch railway companies initially observed a variety
+# of times, most of them had adopted Amsterdam mean time by 1858 but it
+# was not until 1866 when they were all required by law to observe
+# Amsterdam mean time.
+
+# The data before 1945 are taken from
+# <http://www.phys.uu.nl/~vgent/wettijd/wettijd.htm>.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Neth 1916 only - May 1 0:00 1:00 NST # Netherlands Summer Time
+Rule Neth 1916 only - Oct 1 0:00 0 AMT # Amsterdam Mean Time
+Rule Neth 1917 only - Apr 16 2:00s 1:00 NST
+Rule Neth 1917 only - Sep 17 2:00s 0 AMT
+Rule Neth 1918 1921 - Apr Mon>=1 2:00s 1:00 NST
+Rule Neth 1918 1921 - Sep lastMon 2:00s 0 AMT
+Rule Neth 1922 only - Mar lastSun 2:00s 1:00 NST
+Rule Neth 1922 1936 - Oct Sun>=2 2:00s 0 AMT
+Rule Neth 1923 only - Jun Fri>=1 2:00s 1:00 NST
+Rule Neth 1924 only - Mar lastSun 2:00s 1:00 NST
+Rule Neth 1925 only - Jun Fri>=1 2:00s 1:00 NST
+# From 1926 through 1939 DST began 05-15, except that it was delayed by a week
+# in years when 05-15 fell in the Pentecost weekend.
+Rule Neth 1926 1931 - May 15 2:00s 1:00 NST
+Rule Neth 1932 only - May 22 2:00s 1:00 NST
+Rule Neth 1933 1936 - May 15 2:00s 1:00 NST
+Rule Neth 1937 only - May 22 2:00s 1:00 NST
+Rule Neth 1937 only - Jul 1 0:00 1:00 S
+Rule Neth 1937 1939 - Oct Sun>=2 2:00s 0 -
+Rule Neth 1938 1939 - May 15 2:00s 1:00 S
+Rule Neth 1945 only - Apr 2 2:00s 1:00 S
+Rule Neth 1945 only - Sep 16 2:00s 0 -
+#
+# Amsterdam Mean Time was +00:19:32.13 exactly, but the .13 is omitted
+# below because the current format requires GMTOFF to be an integer.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Amsterdam 0:19:32 - LMT 1835
+ 0:19:32 Neth %s 1937 Jul 1
+ 0:20 Neth NE%sT 1940 May 16 0:00 # Dutch Time
+ 1:00 C-Eur CE%sT 1945 Apr 2 2:00
+ 1:00 Neth CE%sT 1977
+ 1:00 EU CE%sT
+
+# Norway
+# http://met.no/met/met_lex/q_u/sommertid.html (2004-01) agrees with Shanks &
+# Pottenger.
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Norway 1916 only - May 22 1:00 1:00 S
+Rule Norway 1916 only - Sep 30 0:00 0 -
+Rule Norway 1945 only - Apr 2 2:00s 1:00 S
+Rule Norway 1945 only - Oct 1 2:00s 0 -
+Rule Norway 1959 1964 - Mar Sun>=15 2:00s 1:00 S
+Rule Norway 1959 1965 - Sep Sun>=15 2:00s 0 -
+Rule Norway 1965 only - Apr 25 2:00s 1:00 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Oslo 0:43:00 - LMT 1895 Jan 1
+ 1:00 Norway CE%sT 1940 Aug 10 23:00
+ 1:00 C-Eur CE%sT 1945 Apr 2 2:00
+ 1:00 Norway CE%sT 1980
+ 1:00 EU CE%sT
+
+# Svalbard & Jan Mayen
+
+# From Steffen Thorsen (2001-05-01):
+# Although I could not find it explicitly, it seems that Jan Mayen and
+# Svalbard have been using the same time as Norway at least since the
+# time they were declared as parts of Norway. Svalbard was declared
+# as a part of Norway by law of 1925-07-17 no 11, section 4 and Jan
+# Mayen by law of 1930-02-27 no 2, section 2. (From
+# http://www.lovdata.no/all/nl-19250717-011.html and
+# http://www.lovdata.no/all/nl-19300227-002.html). The law/regulation
+# for normal/standard time in Norway is from 1894-06-29 no 1 (came
+# into operation on 1895-01-01) and Svalbard/Jan Mayen seem to be a
+# part of this law since 1925/1930. (From
+# http://www.lovdata.no/all/nl-18940629-001.html ) I have not been
+# able to find if Jan Mayen used a different time zone (e.g. -0100)
+# before 1930. Jan Mayen has only been "inhabitated" since 1921 by
+# Norwegian meteorologists and maybe used the same time as Norway ever
+# since 1921. Svalbard (Arctic/Longyearbyen) has been inhabited since
+# before 1895, and therefore probably changed the local time somewhere
+# between 1895 and 1925 (inclusive).
+
+# From Paul Eggert (2001-05-01):
+#
+# Actually, Jan Mayen was never occupied by Germany during World War II,
+# so it must have diverged from Oslo time during the war, as Oslo was
+# keeping Berlin time.
+#
+# <http://home.no.net/janmayen/history.htm> says that the meteorologists
+# burned down their station in 1940 and left the island, but returned in
+# 1941 with a small Norwegian garrison and continued operations despite
+# frequent air ttacks from Germans. In 1943 the Americans established a
+# radiolocating station on the island, called "Atlantic City". Possibly
+# the UTC offset changed during the war, but I think it unlikely that
+# Jan Mayen used German daylight-saving rules.
+#
+# Svalbard is more complicated, as it was raided in August 1941 by an
+# Allied party that evacuated the civilian population to England (says
+# <http://www.bartleby.com/65/sv/Svalbard.html>). The Svalbard FAQ
+# <http://www.svalbard.com/SvalbardFAQ.html> says that the Germans were
+# expelled on 1942-05-14. However, small parties of Germans did return,
+# and according to Wilhelm Dege's book "War North of 80" (1954)
+# <http://www.ucalgary.ca/UofC/departments/UP/1-55238/1-55238-110-2.html>
+# the German armed forces at the Svalbard weather station code-named
+# Haudegen did not surrender to the Allies until September 1945.
+#
+# All these events predate our cutoff date of 1970. Unless we can
+# come up with more definitive info about the timekeeping during the
+# war years it's probably best just do do the following for now:
+Link Europe/Oslo Arctic/Longyearbyen
+
+# Poland
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Poland 1918 1919 - Sep 16 2:00s 0 -
+Rule Poland 1919 only - Apr 15 2:00s 1:00 S
+Rule Poland 1944 only - Apr 3 2:00s 1:00 S
+# Whitman gives 1944 Nov 30; go with Shanks & Pottenger.
+Rule Poland 1944 only - Oct 4 2:00 0 -
+# For 1944-1948 Whitman gives the previous day; go with Shanks & Pottenger.
+Rule Poland 1945 only - Apr 29 0:00 1:00 S
+Rule Poland 1945 only - Nov 1 0:00 0 -
+# For 1946 on the source is Kazimierz Borkowski,
+# Torun Center for Astronomy, Dept. of Radio Astronomy, Nicolaus Copernicus U.,
+# <http://www.astro.uni.torun.pl/~kb/Artykuly/U-PA/Czas2.htm#tth_tAb1>
+# Thanks to Przemyslaw Augustyniak (2005-05-28) for this reference.
+# He also gives these further references:
+# Mon Pol nr 13, poz 162 (1995) <http://www.abc.com.pl/serwis/mp/1995/0162.htm>
+# Druk nr 2180 (2003) <http://www.senat.gov.pl/k5/dok/sejm/053/2180.pdf>
+Rule Poland 1946 only - Apr 14 0:00s 1:00 S
+Rule Poland 1946 only - Oct 7 2:00s 0 -
+Rule Poland 1947 only - May 4 2:00s 1:00 S
+Rule Poland 1947 1949 - Oct Sun>=1 2:00s 0 -
+Rule Poland 1948 only - Apr 18 2:00s 1:00 S
+Rule Poland 1949 only - Apr 10 2:00s 1:00 S
+Rule Poland 1957 only - Jun 2 1:00s 1:00 S
+Rule Poland 1957 1958 - Sep lastSun 1:00s 0 -
+Rule Poland 1958 only - Mar 30 1:00s 1:00 S
+Rule Poland 1959 only - May 31 1:00s 1:00 S
+Rule Poland 1959 1961 - Oct Sun>=1 1:00s 0 -
+Rule Poland 1960 only - Apr 3 1:00s 1:00 S
+Rule Poland 1961 1964 - May lastSun 1:00s 1:00 S
+Rule Poland 1962 1964 - Sep lastSun 1:00s 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Warsaw 1:24:00 - LMT 1880
+ 1:24:00 - WMT 1915 Aug 5 # Warsaw Mean Time
+ 1:00 C-Eur CE%sT 1918 Sep 16 3:00
+ 2:00 Poland EE%sT 1922 Jun
+ 1:00 Poland CE%sT 1940 Jun 23 2:00
+ 1:00 C-Eur CE%sT 1944 Oct
+ 1:00 Poland CE%sT 1977
+ 1:00 W-Eur CE%sT 1988
+ 1:00 EU CE%sT
+
+# Portugal
+#
+# From Rui Pedro Salgueiro (1992-11-12):
+# Portugal has recently (September, 27) changed timezone
+# (from WET to MET or CET) to harmonize with EEC.
+#
+# Martin Bruckmann (1996-02-29) reports via Peter Ilieve
+# that Portugal is reverting to 0:00 by not moving its clocks this spring.
+# The new Prime Minister was fed up with getting up in the dark in the winter.
+#
+# From Paul Eggert (1996-11-12):
+# IATA SSIM (1991-09) reports several 1991-09 and 1992-09 transitions
+# at 02:00u, not 01:00u. Assume that these are typos.
+# IATA SSIM (1991/1992) reports that the Azores were at -1:00.
+# IATA SSIM (1993-02) says +0:00; later issues (through 1996-09) say -1:00.
+# Guess that the Azores changed to EU rules in 1992 (since that's when Portugal
+# harmonized with the EU), and that they stayed +0:00 that winter.
+#
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+# DSH writes that despite Decree 1,469 (1915), the change to the clocks was not
+# done every year, depending on what Spain did, because of railroad schedules.
+# Go with Shanks & Pottenger.
+Rule Port 1916 only - Jun 17 23:00 1:00 S
+# Whitman gives 1916 Oct 31; go with Shanks & Pottenger.
+Rule Port 1916 only - Nov 1 1:00 0 -
+Rule Port 1917 only - Feb 28 23:00s 1:00 S
+Rule Port 1917 1921 - Oct 14 23:00s 0 -
+Rule Port 1918 only - Mar 1 23:00s 1:00 S
+Rule Port 1919 only - Feb 28 23:00s 1:00 S
+Rule Port 1920 only - Feb 29 23:00s 1:00 S
+Rule Port 1921 only - Feb 28 23:00s 1:00 S
+Rule Port 1924 only - Apr 16 23:00s 1:00 S
+Rule Port 1924 only - Oct 14 23:00s 0 -
+Rule Port 1926 only - Apr 17 23:00s 1:00 S
+Rule Port 1926 1929 - Oct Sat>=1 23:00s 0 -
+Rule Port 1927 only - Apr 9 23:00s 1:00 S
+Rule Port 1928 only - Apr 14 23:00s 1:00 S
+Rule Port 1929 only - Apr 20 23:00s 1:00 S
+Rule Port 1931 only - Apr 18 23:00s 1:00 S
+# Whitman gives 1931 Oct 8; go with Shanks & Pottenger.
+Rule Port 1931 1932 - Oct Sat>=1 23:00s 0 -
+Rule Port 1932 only - Apr 2 23:00s 1:00 S
+Rule Port 1934 only - Apr 7 23:00s 1:00 S
+# Whitman gives 1934 Oct 5; go with Shanks & Pottenger.
+Rule Port 1934 1938 - Oct Sat>=1 23:00s 0 -
+# Shanks & Pottenger give 1935 Apr 30; go with Whitman.
+Rule Port 1935 only - Mar 30 23:00s 1:00 S
+Rule Port 1936 only - Apr 18 23:00s 1:00 S
+# Whitman gives 1937 Apr 2; go with Shanks & Pottenger.
+Rule Port 1937 only - Apr 3 23:00s 1:00 S
+Rule Port 1938 only - Mar 26 23:00s 1:00 S
+Rule Port 1939 only - Apr 15 23:00s 1:00 S
+# Whitman gives 1939 Oct 7; go with Shanks & Pottenger.
+Rule Port 1939 only - Nov 18 23:00s 0 -
+Rule Port 1940 only - Feb 24 23:00s 1:00 S
+# Shanks & Pottenger give 1940 Oct 7; go with Whitman.
+Rule Port 1940 1941 - Oct 5 23:00s 0 -
+Rule Port 1941 only - Apr 5 23:00s 1:00 S
+Rule Port 1942 1945 - Mar Sat>=8 23:00s 1:00 S
+Rule Port 1942 only - Apr 25 22:00s 2:00 M # Midsummer
+Rule Port 1942 only - Aug 15 22:00s 1:00 S
+Rule Port 1942 1945 - Oct Sat>=24 23:00s 0 -
+Rule Port 1943 only - Apr 17 22:00s 2:00 M
+Rule Port 1943 1945 - Aug Sat>=25 22:00s 1:00 S
+Rule Port 1944 1945 - Apr Sat>=21 22:00s 2:00 M
+Rule Port 1946 only - Apr Sat>=1 23:00s 1:00 S
+Rule Port 1946 only - Oct Sat>=1 23:00s 0 -
+Rule Port 1947 1949 - Apr Sun>=1 2:00s 1:00 S
+Rule Port 1947 1949 - Oct Sun>=1 2:00s 0 -
+# Shanks & Pottenger say DST was observed in 1950; go with Whitman.
+# Whitman gives Oct lastSun for 1952 on; go with Shanks & Pottenger.
+Rule Port 1951 1965 - Apr Sun>=1 2:00s 1:00 S
+Rule Port 1951 1965 - Oct Sun>=1 2:00s 0 -
+Rule Port 1977 only - Mar 27 0:00s 1:00 S
+Rule Port 1977 only - Sep 25 0:00s 0 -
+Rule Port 1978 1979 - Apr Sun>=1 0:00s 1:00 S
+Rule Port 1978 only - Oct 1 0:00s 0 -
+Rule Port 1979 1982 - Sep lastSun 1:00s 0 -
+Rule Port 1980 only - Mar lastSun 0:00s 1:00 S
+Rule Port 1981 1982 - Mar lastSun 1:00s 1:00 S
+Rule Port 1983 only - Mar lastSun 2:00s 1:00 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Shanks & Pottenger say the transition from LMT to WET occurred 1911-05-24;
+# Willett says 1912-01-01. Go with Willett.
+Zone Europe/Lisbon -0:36:32 - LMT 1884
+ -0:36:32 - LMT 1912 Jan 1 # Lisbon Mean Time
+ 0:00 Port WE%sT 1966 Apr 3 2:00
+ 1:00 - CET 1976 Sep 26 1:00
+ 0:00 Port WE%sT 1983 Sep 25 1:00s
+ 0:00 W-Eur WE%sT 1992 Sep 27 1:00s
+ 1:00 EU CE%sT 1996 Mar 31 1:00u
+ 0:00 EU WE%sT
+Zone Atlantic/Azores -1:42:40 - LMT 1884 # Ponta Delgada
+ -1:54:32 - HMT 1911 May 24 # Horta Mean Time
+ -2:00 Port AZO%sT 1966 Apr 3 2:00 # Azores Time
+ -1:00 Port AZO%sT 1983 Sep 25 1:00s
+ -1:00 W-Eur AZO%sT 1992 Sep 27 1:00s
+ 0:00 EU WE%sT 1993 Mar 28 1:00u
+ -1:00 EU AZO%sT
+Zone Atlantic/Madeira -1:07:36 - LMT 1884 # Funchal
+ -1:07:36 - FMT 1911 May 24 # Funchal Mean Time
+ -1:00 Port MAD%sT 1966 Apr 3 2:00 # Madeira Time
+ 0:00 Port WE%sT 1983 Sep 25 1:00s
+ 0:00 EU WE%sT
+
+# Romania
+#
+# From Paul Eggert (1999-10-07):
+# <a href="http://www.nineoclock.ro/POL/1778pol.html">
+# Nine O'clock</a> (1998-10-23) reports that the switch occurred at
+# 04:00 local time in fall 1998. For lack of better info,
+# assume that Romania and Moldova switched to EU rules in 1997,
+# the same year as Bulgaria.
+#
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Romania 1932 only - May 21 0:00s 1:00 S
+Rule Romania 1932 1939 - Oct Sun>=1 0:00s 0 -
+Rule Romania 1933 1939 - Apr Sun>=2 0:00s 1:00 S
+Rule Romania 1979 only - May 27 0:00 1:00 S
+Rule Romania 1979 only - Sep lastSun 0:00 0 -
+Rule Romania 1980 only - Apr 5 23:00 1:00 S
+Rule Romania 1980 only - Sep lastSun 1:00 0 -
+Rule Romania 1991 1993 - Mar lastSun 0:00s 1:00 S
+Rule Romania 1991 1993 - Sep lastSun 0:00s 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Bucharest 1:44:24 - LMT 1891 Oct
+ 1:44:24 - BMT 1931 Jul 24 # Bucharest MT
+ 2:00 Romania EE%sT 1981 Mar 29 2:00s
+ 2:00 C-Eur EE%sT 1991
+ 2:00 Romania EE%sT 1994
+ 2:00 E-Eur EE%sT 1997
+ 2:00 EU EE%sT
+
+# Russia
+
+# From Paul Eggert (2006-03-22):
+# Except for Moscow after 1919-07-01, I invented the time zone abbreviations.
+# Moscow time zone abbreviations after 1919-07-01, and Moscow rules after 1991,
+# are from Andrey A. Chernov. The rest is from Shanks & Pottenger,
+# except we follow Chernov's report that 1992 DST transitions were Sat
+# 23:00, not Sun 02:00s.
+#
+# From Stanislaw A. Kuzikowski (1994-06-29):
+# But now it is some months since Novosibirsk is 3 hours ahead of Moscow!
+# I do not know why they have decided to make this change;
+# as far as I remember it was done exactly during winter->summer switching
+# so we (Novosibirsk) simply did not switch.
+#
+# From Andrey A. Chernov (1996-10-04):
+# `MSK' and `MSD' were born and used initially on Moscow computers with
+# UNIX-like OSes by several developer groups (e.g. Demos group, Kiae group)....
+# The next step was the UUCP network, the Relcom predecessor
+# (used mainly for mail), and MSK/MSD was actively used there.
+#
+# From Chris Carrier (1996-10-30):
+# According to a friend of mine who rode the Trans-Siberian Railroad from
+# Moscow to Irkutsk in 1995, public air and rail transport in Russia ...
+# still follows Moscow time, no matter where in Russia it is located.
+#
+# For Grozny, Chechnya, we have the following story from
+# John Daniszewski, "Scavengers in the Rubble", Los Angeles Times (2001-02-07):
+# News--often false--is spread by word of mouth. A rumor that it was
+# time to move the clocks back put this whole city out of sync with
+# the rest of Russia for two weeks--even soldiers stationed here began
+# enforcing curfew at the wrong time.
+#
+# From Gwillim Law (2001-06-05):
+# There's considerable evidence that Sakhalin Island used to be in
+# UTC+11, and has changed to UTC+10, in this decade. I start with the
+# SSIM, which listed Yuzhno-Sakhalinsk in zone RU10 along with Magadan
+# until February 1997, and then in RU9 with Khabarovsk and Vladivostok
+# since September 1997.... Although the Kuril Islands are
+# administratively part of Sakhalin oblast', they appear to have
+# remained on UTC+11 along with Magadan.
+#
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+#
+# Kaliningradskaya oblast'.
+Zone Europe/Kaliningrad 1:22:00 - LMT 1893 Apr
+ 1:00 C-Eur CE%sT 1945
+ 2:00 Poland CE%sT 1946
+ 3:00 Russia MSK/MSD 1991 Mar 31 2:00s
+ 2:00 Russia EE%sT
+#
+# From Oscar van Vlijmen (2001-08-25): [This region consists of]
+# Respublika Adygeya, Arkhangel'skaya oblast',
+# Belgorodskaya oblast', Bryanskaya oblast', Vladimirskaya oblast',
+# Vologodskaya oblast', Voronezhskaya oblast',
+# Respublika Dagestan, Ivanovskaya oblast', Respublika Ingushetiya,
+# Kabarbino-Balkarskaya Respublika, Respublika Kalmykiya,
+# Kalyzhskaya oblast', Respublika Karachaevo-Cherkessiya,
+# Respublika Kareliya, Respublika Komi,
+# Kostromskaya oblast', Krasnodarskij kraj, Kurskaya oblast',
+# Leningradskaya oblast', Lipetskaya oblast', Respublika Marij El,
+# Respublika Mordoviya, Moskva, Moskovskaya oblast',
+# Murmanskaya oblast', Nenetskij avtonomnyj okrug,
+# Nizhegorodskaya oblast', Novgorodskaya oblast', Orlovskaya oblast',
+# Penzenskaya oblast', Pskovskaya oblast', Rostovskaya oblast',
+# Ryazanskaya oblast', Sankt-Peterburg,
+# Respublika Severnaya Osetiya, Smolenskaya oblast',
+# Stavropol'skij kraj, Tambovskaya oblast', Respublika Tatarstan,
+# Tverskaya oblast', Tyl'skaya oblast', Ul'yanovskaya oblast',
+# Chechenskaya Respublika, Chuvashskaya oblast',
+# Yaroslavskaya oblast'
+Zone Europe/Moscow 2:30:20 - LMT 1880
+ 2:30 - MMT 1916 Jul 3 # Moscow Mean Time
+ 2:30:48 Russia %s 1919 Jul 1 2:00
+ 3:00 Russia MSK/MSD 1922 Oct
+ 2:00 - EET 1930 Jun 21
+ 3:00 Russia MSK/MSD 1991 Mar 31 2:00s
+ 2:00 Russia EE%sT 1992 Jan 19 2:00s
+ 3:00 Russia MSK/MSD
+#
+# Astrakhanskaya oblast', Kirovskaya oblast', Saratovskaya oblast',
+# Volgogradskaya oblast'. Shanks & Pottenger say Kirov is still at +0400
+# but Wikipedia (2006-05-09) says +0300. Perhaps it switched after the
+# others? But we have no data.
+Zone Europe/Volgograd 2:57:40 - LMT 1920 Jan 3
+ 3:00 - TSAT 1925 Apr 6 # Tsaritsyn Time
+ 3:00 - STAT 1930 Jun 21 # Stalingrad Time
+ 4:00 - STAT 1961 Nov 11
+ 4:00 Russia VOL%sT 1989 Mar 26 2:00s # Volgograd T
+ 3:00 Russia VOL%sT 1991 Mar 31 2:00s
+ 4:00 - VOLT 1992 Mar 29 2:00s
+ 3:00 Russia VOL%sT
+#
+# From Oscar van Vlijmen (2001-08-25): [This region consists of]
+# Samarskaya oblast', Udmyrtskaya respublika
+Zone Europe/Samara 3:20:36 - LMT 1919 Jul 1 2:00
+ 3:00 - SAMT 1930 Jun 21
+ 4:00 - SAMT 1935 Jan 27
+ 4:00 Russia KUY%sT 1989 Mar 26 2:00s # Kuybyshev
+ 3:00 Russia KUY%sT 1991 Mar 31 2:00s
+ 2:00 Russia KUY%sT 1991 Sep 29 2:00s
+ 3:00 - KUYT 1991 Oct 20 3:00
+ 4:00 Russia SAM%sT # Samara Time
+#
+# From Oscar van Vlijmen (2001-08-25): [This region consists of]
+# Respublika Bashkortostan, Komi-Permyatskij avtonomnyj okrug,
+# Kurganskaya oblast', Orenburgskaya oblast', Permskaya oblast',
+# Sverdlovskaya oblast', Tyumenskaya oblast',
+# Khanty-Manskijskij avtonomnyj okrug, Chelyabinskaya oblast',
+# Yamalo-Nenetskij avtonomnyj okrug.
+Zone Asia/Yekaterinburg 4:02:24 - LMT 1919 Jul 15 4:00
+ 4:00 - SVET 1930 Jun 21 # Sverdlovsk Time
+ 5:00 Russia SVE%sT 1991 Mar 31 2:00s
+ 4:00 Russia SVE%sT 1992 Jan 19 2:00s
+ 5:00 Russia YEK%sT # Yekaterinburg Time
+#
+# From Oscar van Vlijmen (2001-08-25): [This region consists of]
+# Respublika Altaj, Altajskij kraj, Omskaya oblast'.
+Zone Asia/Omsk 4:53:36 - LMT 1919 Nov 14
+ 5:00 - OMST 1930 Jun 21 # Omsk TIme
+ 6:00 Russia OMS%sT 1991 Mar 31 2:00s
+ 5:00 Russia OMS%sT 1992 Jan 19 2:00s
+ 6:00 Russia OMS%sT
+#
+# From Paul Eggert (2006-08-19): I'm guessing about Tomsk here; it's
+# not clear when it switched from +7 to +6.
+# Novosibirskaya oblast', Tomskaya oblast'.
+Zone Asia/Novosibirsk 5:31:40 - LMT 1919 Dec 14 6:00
+ 6:00 - NOVT 1930 Jun 21 # Novosibirsk Time
+ 7:00 Russia NOV%sT 1991 Mar 31 2:00s
+ 6:00 Russia NOV%sT 1992 Jan 19 2:00s
+ 7:00 Russia NOV%sT 1993 May 23 # say Shanks & P.
+ 6:00 Russia NOV%sT
+#
+# From Oscar van Vlijmen (2001-08-25): [This region consists of]
+# Kemerovskaya oblast', Krasnoyarskij kraj,
+# Tajmyrskij (Dolgano-Nenetskij) avtonomnyj okrug,
+# Respublika Tuva, Respublika Khakasiya, Evenkijskij avtonomnyj okrug.
+Zone Asia/Krasnoyarsk 6:11:20 - LMT 1920 Jan 6
+ 6:00 - KRAT 1930 Jun 21 # Krasnoyarsk Time
+ 7:00 Russia KRA%sT 1991 Mar 31 2:00s
+ 6:00 Russia KRA%sT 1992 Jan 19 2:00s
+ 7:00 Russia KRA%sT
+#
+# From Oscar van Vlijmen (2001-08-25): [This region consists of]
+# Respublika Buryatiya, Irkutskaya oblast',
+# Ust'-Ordynskij Buryatskij avtonomnyj okrug.
+Zone Asia/Irkutsk 6:57:20 - LMT 1880
+ 6:57:20 - IMT 1920 Jan 25 # Irkutsk Mean Time
+ 7:00 - IRKT 1930 Jun 21 # Irkutsk Time
+ 8:00 Russia IRK%sT 1991 Mar 31 2:00s
+ 7:00 Russia IRK%sT 1992 Jan 19 2:00s
+ 8:00 Russia IRK%sT
+#
+# From Oscar van Vlijmen (2003-10-18): [This region consists of]
+# Aginskij Buryatskij avtonomnyj okrug, Amurskaya oblast',
+# [parts of] Respublika Sakha (Yakutiya), Chitinskaya oblast'.
+# The Sakha districts are: Aldanskij, Amginskij, Anabarskij,
+# Bulunskij, Verkhnekolymskij, Verkhnevilyujskij, Vilyujskij, Gornyj,
+# Zhiganskij, Kobyajskij, Lenskij, Megino-Kangalasskij, Mirninskij,
+# Namskij, Nyurbinskij, Olenekskij, Olekminskij, Srednekolymskij,
+# Suntarskij, Tattinskij, Ust'-Aldanskij, Khangalasskij,
+# Churapchinskij, Eveno-Bytantajskij.
+Zone Asia/Yakutsk 8:38:40 - LMT 1919 Dec 15
+ 8:00 - YAKT 1930 Jun 21 # Yakutsk Time
+ 9:00 Russia YAK%sT 1991 Mar 31 2:00s
+ 8:00 Russia YAK%sT 1992 Jan 19 2:00s
+ 9:00 Russia YAK%sT
+#
+# From Oscar van Vlijmen (2003-10-18): [This region consists of]
+# Evrejskaya avtonomnaya oblast', Khabarovskij kraj, Primorskij kraj,
+# [parts of] Respublika Sakha (Yakutiya).
+# The Sakha districts are: Verkhoyanskij, Tomponskij, Ust'-Majskij,
+# Ust'-Yanskij.
+Zone Asia/Vladivostok 8:47:44 - LMT 1922 Nov 15
+ 9:00 - VLAT 1930 Jun 21 # Vladivostok Time
+ 10:00 Russia VLA%sT 1991 Mar 31 2:00s
+ 9:00 Russia VLA%sST 1992 Jan 19 2:00s
+ 10:00 Russia VLA%sT
+#
+# Sakhalinskaya oblast'.
+# The Zone name should be Yuzhno-Sakhalinsk, but that's too long.
+Zone Asia/Sakhalin 9:30:48 - LMT 1905 Aug 23
+ 9:00 - CJT 1938
+ 9:00 - JST 1945 Aug 25
+ 11:00 Russia SAK%sT 1991 Mar 31 2:00s # Sakhalin T.
+ 10:00 Russia SAK%sT 1992 Jan 19 2:00s
+ 11:00 Russia SAK%sT 1997 Mar lastSun 2:00s
+ 10:00 Russia SAK%sT
+#
+# From Oscar van Vlijmen (2003-10-18): [This region consists of]
+# Magadanskaya oblast', Respublika Sakha (Yakutiya).
+# Probably also: Kuril Islands.
+# The Sakha districts are: Abyjskij, Allaikhovskij, Momskij,
+# Nizhnekolymskij, Ojmyakonskij.
+Zone Asia/Magadan 10:03:12 - LMT 1924 May 2
+ 10:00 - MAGT 1930 Jun 21 # Magadan Time
+ 11:00 Russia MAG%sT 1991 Mar 31 2:00s
+ 10:00 Russia MAG%sT 1992 Jan 19 2:00s
+ 11:00 Russia MAG%sT
+#
+# From Oscar van Vlijmen (2001-08-25): [This region consists of]
+# Kamchatskaya oblast', Koryakskij avtonomnyj okrug.
+#
+# The Zone name should be Asia/Petropavlovsk-Kamchatski, but that's too long.
+Zone Asia/Kamchatka 10:34:36 - LMT 1922 Nov 10
+ 11:00 - PETT 1930 Jun 21 # P-K Time
+ 12:00 Russia PET%sT 1991 Mar 31 2:00s
+ 11:00 Russia PET%sT 1992 Jan 19 2:00s
+ 12:00 Russia PET%sT
+#
+# Chukotskij avtonomnyj okrug
+Zone Asia/Anadyr 11:49:56 - LMT 1924 May 2
+ 12:00 - ANAT 1930 Jun 21 # Anadyr Time
+ 13:00 Russia ANA%sT 1982 Apr 1 0:00s
+ 12:00 Russia ANA%sT 1991 Mar 31 2:00s
+ 11:00 Russia ANA%sT 1992 Jan 19 2:00s
+ 12:00 Russia ANA%sT
+
+# Serbia
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Belgrade 1:22:00 - LMT 1884
+ 1:00 - CET 1941 Apr 18 23:00
+ 1:00 C-Eur CE%sT 1945
+ 1:00 - CET 1945 May 8 2:00s
+ 1:00 1:00 CEST 1945 Sep 16 2:00s
+# Metod Kozelj reports that the legal date of
+# transition to EU rules was 1982-11-27, for all of Yugoslavia at the time.
+# Shanks & Pottenger don't give as much detail, so go with Kozelj.
+ 1:00 - CET 1982 Nov 27
+ 1:00 EU CE%sT
+Link Europe/Belgrade Europe/Ljubljana # Slovenia
+Link Europe/Belgrade Europe/Podgorica # Montenegro
+Link Europe/Belgrade Europe/Sarajevo # Bosnia and Herzegovina
+Link Europe/Belgrade Europe/Skopje # Macedonia
+Link Europe/Belgrade Europe/Zagreb # Croatia
+
+# Slovakia
+Link Europe/Prague Europe/Bratislava
+
+# Slovenia
+# see Serbia
+
+# Spain
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+# For 1917-1919 Whitman gives Apr Sat>=1 - Oct Sat>=1;
+# go with Shanks & Pottenger.
+Rule Spain 1917 only - May 5 23:00s 1:00 S
+Rule Spain 1917 1919 - Oct 6 23:00s 0 -
+Rule Spain 1918 only - Apr 15 23:00s 1:00 S
+Rule Spain 1919 only - Apr 5 23:00s 1:00 S
+# Whitman gives 1921 Feb 28 - Oct 14; go with Shanks & Pottenger.
+Rule Spain 1924 only - Apr 16 23:00s 1:00 S
+# Whitman gives 1924 Oct 14; go with Shanks & Pottenger.
+Rule Spain 1924 only - Oct 4 23:00s 0 -
+Rule Spain 1926 only - Apr 17 23:00s 1:00 S
+# Whitman says no DST in 1929; go with Shanks & Pottenger.
+Rule Spain 1926 1929 - Oct Sat>=1 23:00s 0 -
+Rule Spain 1927 only - Apr 9 23:00s 1:00 S
+Rule Spain 1928 only - Apr 14 23:00s 1:00 S
+Rule Spain 1929 only - Apr 20 23:00s 1:00 S
+# Whitman gives 1937 Jun 16, 1938 Apr 16, 1940 Apr 13;
+# go with Shanks & Pottenger.
+Rule Spain 1937 only - May 22 23:00s 1:00 S
+Rule Spain 1937 1939 - Oct Sat>=1 23:00s 0 -
+Rule Spain 1938 only - Mar 22 23:00s 1:00 S
+Rule Spain 1939 only - Apr 15 23:00s 1:00 S
+Rule Spain 1940 only - Mar 16 23:00s 1:00 S
+# Whitman says no DST 1942-1945; go with Shanks & Pottenger.
+Rule Spain 1942 only - May 2 22:00s 2:00 M # Midsummer
+Rule Spain 1942 only - Sep 1 22:00s 1:00 S
+Rule Spain 1943 1946 - Apr Sat>=13 22:00s 2:00 M
+Rule Spain 1943 only - Oct 3 22:00s 1:00 S
+Rule Spain 1944 only - Oct 10 22:00s 1:00 S
+Rule Spain 1945 only - Sep 30 1:00 1:00 S
+Rule Spain 1946 only - Sep 30 0:00 0 -
+Rule Spain 1949 only - Apr 30 23:00 1:00 S
+Rule Spain 1949 only - Sep 30 1:00 0 -
+Rule Spain 1974 1975 - Apr Sat>=13 23:00 1:00 S
+Rule Spain 1974 1975 - Oct Sun>=1 1:00 0 -
+Rule Spain 1976 only - Mar 27 23:00 1:00 S
+Rule Spain 1976 1977 - Sep lastSun 1:00 0 -
+Rule Spain 1977 1978 - Apr 2 23:00 1:00 S
+Rule Spain 1978 only - Oct 1 1:00 0 -
+# The following rules are copied from Morocco from 1967 through 1978.
+Rule SpainAfrica 1967 only - Jun 3 12:00 1:00 S
+Rule SpainAfrica 1967 only - Oct 1 0:00 0 -
+Rule SpainAfrica 1974 only - Jun 24 0:00 1:00 S
+Rule SpainAfrica 1974 only - Sep 1 0:00 0 -
+Rule SpainAfrica 1976 1977 - May 1 0:00 1:00 S
+Rule SpainAfrica 1976 only - Aug 1 0:00 0 -
+Rule SpainAfrica 1977 only - Sep 28 0:00 0 -
+Rule SpainAfrica 1978 only - Jun 1 0:00 1:00 S
+Rule SpainAfrica 1978 only - Aug 4 0:00 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Madrid -0:14:44 - LMT 1901 Jan 1 0:00s
+ 0:00 Spain WE%sT 1946 Sep 30
+ 1:00 Spain CE%sT 1979
+ 1:00 EU CE%sT
+Zone Africa/Ceuta -0:21:16 - LMT 1901
+ 0:00 - WET 1918 May 6 23:00
+ 0:00 1:00 WEST 1918 Oct 7 23:00
+ 0:00 - WET 1924
+ 0:00 Spain WE%sT 1929
+ 0:00 SpainAfrica WE%sT 1984 Mar 16
+ 1:00 - CET 1986
+ 1:00 EU CE%sT
+Zone Atlantic/Canary -1:01:36 - LMT 1922 Mar # Las Palmas de Gran C.
+ -1:00 - CANT 1946 Sep 30 1:00 # Canaries Time
+ 0:00 - WET 1980 Apr 6 0:00s
+ 0:00 1:00 WEST 1980 Sep 28 0:00s
+ 0:00 EU WE%sT
+# IATA SSIM (1996-09) says the Canaries switch at 2:00u, not 1:00u.
+# Ignore this for now, as the Canaries are part of the EU.
+
+# Sweden
+
+# From Ivan Nilsson (2001-04-13), superseding Shanks & Pottenger:
+#
+# The law "Svensk forfattningssamling 1878, no 14" about standard time in 1879:
+# From the beginning of 1879 (that is 01-01 00:00) the time for all
+# places in the country is "the mean solar time for the meridian at
+# three degrees, or twelve minutes of time, to the west of the
+# meridian of the Observatory of Stockholm". The law is dated 1878-05-31.
+#
+# The observatory at that time had the meridian 18 degrees 03' 30"
+# eastern longitude = 01:12:14 in time. Less 12 minutes gives the
+# national standard time as 01:00:14 ahead of GMT....
+#
+# About the beginning of CET in Sweden. The lawtext ("Svensk
+# forfattningssamling 1899, no 44") states, that "from the beginning
+# of 1900... ... the same as the mean solar time for the meridian at
+# the distance of one hour of time from the meridian of the English
+# observatory at Greenwich, or at 12 minutes 14 seconds to the west
+# from the meridian of the Observatory of Stockholm". The law is dated
+# 1899-06-16. In short: At 1900-01-01 00:00:00 the new standard time
+# in Sweden is 01:00:00 ahead of GMT.
+#
+# 1916: The lawtext ("Svensk forfattningssamling 1916, no 124") states
+# that "1916-05-15 is considered to begin one hour earlier". It is
+# pretty obvious that at 05-14 23:00 the clocks are set to 05-15 00:00....
+# Further the law says, that "1916-09-30 is considered to end one hour later".
+#
+# The laws regulating [DST] are available on the site of the Swedish
+# Parliament beginning with 1985 - the laws regulating 1980/1984 are
+# not available on the site (to my knowledge they are only available
+# in Swedish): <http://www.riksdagen.se/english/work/sfst.asp> (type
+# "sommartid" without the quotes in the field "Fritext" and then click
+# the Sok-button).
+#
+# (2001-05-13):
+#
+# I have now found a newspaper stating that at 1916-10-01 01:00
+# summertime the church-clocks etc were set back one hour to show
+# 1916-10-01 00:00 standard time. The article also reports that some
+# people thought the switch to standard time would take place already
+# at 1916-10-01 00:00 summer time, but they had to wait for another
+# hour before the event took place.
+#
+# Source: The newspaper "Dagens Nyheter", 1916-10-01, page 7 upper left.
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Stockholm 1:12:12 - LMT 1879 Jan 1
+ 1:00:14 - SET 1900 Jan 1 # Swedish Time
+ 1:00 - CET 1916 May 14 23:00
+ 1:00 1:00 CEST 1916 Oct 1 01:00
+ 1:00 - CET 1980
+ 1:00 EU CE%sT
+
+# Switzerland
+# From Howse:
+# By the end of the 18th century clocks and watches became commonplace
+# and their performance improved enormously. Communities began to keep
+# mean time in preference to apparent time -- Geneva from 1780 ....
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+# From Whitman (who writes ``Midnight?''):
+Rule Swiss 1940 only - Nov 2 0:00 1:00 S
+Rule Swiss 1940 only - Dec 31 0:00 0 -
+# From Shanks & Pottenger:
+Rule Swiss 1941 1942 - May Sun>=1 2:00 1:00 S
+Rule Swiss 1941 1942 - Oct Sun>=1 0:00 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Zurich 0:34:08 - LMT 1848 Sep 12
+ 0:29:44 - BMT 1894 Jun # Bern Mean Time
+ 1:00 Swiss CE%sT 1981
+ 1:00 EU CE%sT
+
+# Turkey
+
+# From Amar Devegowda (2007-01-03):
+# The time zone rules for Istanbul, Turkey have not been changed for years now.
+# ... The latest rules are available at -
+# http://www.timeanddate.com/worldclock/timezone.html?n=107
+# From Steffen Thorsen (2007-01-03):
+# I have been able to find press records back to 1996 which all say that
+# DST started 01:00 local time and end at 02:00 local time. I am not sure
+# what happened before that. One example for each year from 1996 to 2001:
+# http://newspot.byegm.gov.tr/arsiv/1996/21/N4.htm
+# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING97/03/97X03X25.TXT
+# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING98/03/98X03X02.HTM
+# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING99/10/99X10X26.HTM#%2016
+# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING2000/03/00X03X06.HTM#%2021
+# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING2001/03/23x03x01.HTM#%2027
+# From Paul Eggert (2007-01-03):
+# Prefer the above source to Shanks & Pottenger for time stamps after 1990.
+
+# From Steffen Thorsen (2007-03-09):
+# Starting 2007 though, it seems that they are adopting EU's 1:00 UTC
+# start/end time, according to the following page (2007-03-07):
+# http://www.ntvmsnbc.com/news/402029.asp
+# The official document is located here - it is in Turkish...:
+# http://rega.basbakanlik.gov.tr/eskiler/2007/03/20070307-7.htm
+# I was able to locate the following seemingly official document
+# (on a non-government server though) describing dates between 2002 and 2006:
+# http://www.alomaliye.com/bkk_2002_3769.htm
+
+# From Sue Williams (2008-08-11):
+# I spotted this news article about a potential change in Turkey.
+#
+# <a href="http://www.hurriyet.com.tr/english/domestic/9626174.asp?scr=1">
+# http://www.hurriyet.com.tr/english/domestic/9626174.asp?scr=1
+# </a>
+
+# From Sue Williams (2008-08-20):
+# This article says that around the end of March 2011, Turkey wants to
+# adjust the clocks forward by 1/2 hour and stay that way permanently.
+# The article indicates that this is a change in timezone offset in addition
+# to stopping observance of DST.
+# This proposal has not yet been approved.
+#
+# Read more here...
+#
+# Turkey to abandon daylight saving time in 2011
+# <a href="http://www.turkishdailynews.com.tr/article.php?enewsid=112989">
+# http://www.turkishdailynews.com.tr/article.php?enewsid=112989
+# </a>
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Turkey 1916 only - May 1 0:00 1:00 S
+Rule Turkey 1916 only - Oct 1 0:00 0 -
+Rule Turkey 1920 only - Mar 28 0:00 1:00 S
+Rule Turkey 1920 only - Oct 25 0:00 0 -
+Rule Turkey 1921 only - Apr 3 0:00 1:00 S
+Rule Turkey 1921 only - Oct 3 0:00 0 -
+Rule Turkey 1922 only - Mar 26 0:00 1:00 S
+Rule Turkey 1922 only - Oct 8 0:00 0 -
+# Whitman gives 1923 Apr 28 - Sep 16 and no DST in 1924-1925;
+# go with Shanks & Pottenger.
+Rule Turkey 1924 only - May 13 0:00 1:00 S
+Rule Turkey 1924 1925 - Oct 1 0:00 0 -
+Rule Turkey 1925 only - May 1 0:00 1:00 S
+Rule Turkey 1940 only - Jun 30 0:00 1:00 S
+Rule Turkey 1940 only - Oct 5 0:00 0 -
+Rule Turkey 1940 only - Dec 1 0:00 1:00 S
+Rule Turkey 1941 only - Sep 21 0:00 0 -
+Rule Turkey 1942 only - Apr 1 0:00 1:00 S
+# Whitman omits the next two transition and gives 1945 Oct 1;
+# go with Shanks & Pottenger.
+Rule Turkey 1942 only - Nov 1 0:00 0 -
+Rule Turkey 1945 only - Apr 2 0:00 1:00 S
+Rule Turkey 1945 only - Oct 8 0:00 0 -
+Rule Turkey 1946 only - Jun 1 0:00 1:00 S
+Rule Turkey 1946 only - Oct 1 0:00 0 -
+Rule Turkey 1947 1948 - Apr Sun>=16 0:00 1:00 S
+Rule Turkey 1947 1950 - Oct Sun>=2 0:00 0 -
+Rule Turkey 1949 only - Apr 10 0:00 1:00 S
+Rule Turkey 1950 only - Apr 19 0:00 1:00 S
+Rule Turkey 1951 only - Apr 22 0:00 1:00 S
+Rule Turkey 1951 only - Oct 8 0:00 0 -
+Rule Turkey 1962 only - Jul 15 0:00 1:00 S
+Rule Turkey 1962 only - Oct 8 0:00 0 -
+Rule Turkey 1964 only - May 15 0:00 1:00 S
+Rule Turkey 1964 only - Oct 1 0:00 0 -
+Rule Turkey 1970 1972 - May Sun>=2 0:00 1:00 S
+Rule Turkey 1970 1972 - Oct Sun>=2 0:00 0 -
+Rule Turkey 1973 only - Jun 3 1:00 1:00 S
+Rule Turkey 1973 only - Nov 4 3:00 0 -
+Rule Turkey 1974 only - Mar 31 2:00 1:00 S
+Rule Turkey 1974 only - Nov 3 5:00 0 -
+Rule Turkey 1975 only - Mar 30 0:00 1:00 S
+Rule Turkey 1975 1976 - Oct lastSun 0:00 0 -
+Rule Turkey 1976 only - Jun 1 0:00 1:00 S
+Rule Turkey 1977 1978 - Apr Sun>=1 0:00 1:00 S
+Rule Turkey 1977 only - Oct 16 0:00 0 -
+Rule Turkey 1979 1980 - Apr Sun>=1 3:00 1:00 S
+Rule Turkey 1979 1982 - Oct Mon>=11 0:00 0 -
+Rule Turkey 1981 1982 - Mar lastSun 3:00 1:00 S
+Rule Turkey 1983 only - Jul 31 0:00 1:00 S
+Rule Turkey 1983 only - Oct 2 0:00 0 -
+Rule Turkey 1985 only - Apr 20 0:00 1:00 S
+Rule Turkey 1985 only - Sep 28 0:00 0 -
+Rule Turkey 1986 1990 - Mar lastSun 2:00s 1:00 S
+Rule Turkey 1986 1990 - Sep lastSun 2:00s 0 -
+Rule Turkey 1991 2006 - Mar lastSun 1:00s 1:00 S
+Rule Turkey 1991 1995 - Sep lastSun 1:00s 0 -
+Rule Turkey 1996 2006 - Oct lastSun 1:00s 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Europe/Istanbul 1:55:52 - LMT 1880
+ 1:56:56 - IMT 1910 Oct # Istanbul Mean Time?
+ 2:00 Turkey EE%sT 1978 Oct 15
+ 3:00 Turkey TR%sT 1985 Apr 20 # Turkey Time
+ 2:00 Turkey EE%sT 2007
+ 2:00 EU EE%sT
+Link Europe/Istanbul Asia/Istanbul # Istanbul is in both continents.
+
+# Ukraine
+#
+# From Igor Karpov, who works for the Ukranian Ministry of Justice,
+# via Garrett Wollman (2003-01-27):
+# BTW, I've found the official document on this matter. It's goverment
+# regulations number 509, May 13, 1996. In my poor translation it says:
+# "Time in Ukraine is set to second timezone (Kiev time). Each last Sunday
+# of March at 3am the time is changing to 4am and each last Sunday of
+# October the time at 4am is changing to 3am"
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Most of Ukraine since 1970 has been like Kiev.
+# "Kyiv" is the transliteration of the Ukrainian name, but
+# "Kiev" is more common in English.
+Zone Europe/Kiev 2:02:04 - LMT 1880
+ 2:02:04 - KMT 1924 May 2 # Kiev Mean Time
+ 2:00 - EET 1930 Jun 21
+ 3:00 - MSK 1941 Sep 20
+ 1:00 C-Eur CE%sT 1943 Nov 6
+ 3:00 Russia MSK/MSD 1990
+ 3:00 - MSK 1990 Jul 1 2:00
+ 2:00 - EET 1992
+ 2:00 E-Eur EE%sT 1995
+ 2:00 EU EE%sT
+# Ruthenia used CET 1990/1991.
+# "Uzhhorod" is the transliteration of the Ukrainian name, but
+# "Uzhgorod" is more common in English.
+Zone Europe/Uzhgorod 1:29:12 - LMT 1890 Oct
+ 1:00 - CET 1940
+ 1:00 C-Eur CE%sT 1944 Oct
+ 1:00 1:00 CEST 1944 Oct 26
+ 1:00 - CET 1945 Jun 29
+ 3:00 Russia MSK/MSD 1990
+ 3:00 - MSK 1990 Jul 1 2:00
+ 1:00 - CET 1991 Mar 31 3:00
+ 2:00 - EET 1992
+ 2:00 E-Eur EE%sT 1995
+ 2:00 EU EE%sT
+# Zaporozh'ye and eastern Lugansk oblasts observed DST 1990/1991.
+# "Zaporizhia" is the transliteration of the Ukrainian name, but
+# "Zaporozh'ye" is more common in English. Use the common English
+# spelling, except omit the apostrophe as it is not allowed in
+# portable Posix file names.
+Zone Europe/Zaporozhye 2:20:40 - LMT 1880
+ 2:20 - CUT 1924 May 2 # Central Ukraine T
+ 2:00 - EET 1930 Jun 21
+ 3:00 - MSK 1941 Aug 25
+ 1:00 C-Eur CE%sT 1943 Oct 25
+ 3:00 Russia MSK/MSD 1991 Mar 31 2:00
+ 2:00 E-Eur EE%sT 1995
+ 2:00 EU EE%sT
+# Central Crimea used Moscow time 1994/1997.
+Zone Europe/Simferopol 2:16:24 - LMT 1880
+ 2:16 - SMT 1924 May 2 # Simferopol Mean T
+ 2:00 - EET 1930 Jun 21
+ 3:00 - MSK 1941 Nov
+ 1:00 C-Eur CE%sT 1944 Apr 13
+ 3:00 Russia MSK/MSD 1990
+ 3:00 - MSK 1990 Jul 1 2:00
+ 2:00 - EET 1992
+# From Paul Eggert (2006-03-22):
+# The _Economist_ (1994-05-28, p 45) reports that central Crimea switched
+# from Kiev to Moscow time sometime after the January 1994 elections.
+# Shanks (1999) says ``date of change uncertain'', but implies that it happened
+# sometime between the 1994 DST switches. Shanks & Pottenger simply say
+# 1994-09-25 03:00, but that can't be right. For now, guess it
+# changed in May.
+ 2:00 E-Eur EE%sT 1994 May
+# From IATA SSIM (1994/1997), which also says that Kerch is still like Kiev.
+ 3:00 E-Eur MSK/MSD 1996 Mar 31 3:00s
+ 3:00 1:00 MSD 1996 Oct 27 3:00s
+# IATA SSIM (1997-09) says Crimea switched to EET/EEST.
+# Assume it happened in March by not changing the clocks.
+ 3:00 Russia MSK/MSD 1997
+ 3:00 - MSK 1997 Mar lastSun 1:00u
+ 2:00 EU EE%sT
+
+###############################################################################
+
+# One source shows that Bulgaria, Cyprus, Finland, and Greece observe DST from
+# the last Sunday in March to the last Sunday in September in 1986.
+# The source shows Romania changing a day later than everybody else.
+#
+# According to Bernard Sieloff's source, Poland is in the MET time zone but
+# uses the WE DST rules. The Western USSR uses EET+1 and ME DST rules.
+# Bernard Sieloff's source claims Romania switches on the same day, but at
+# 00:00 standard time (i.e., 01:00 DST). It also claims that Turkey
+# switches on the same day, but switches on at 01:00 standard time
+# and off at 00:00 standard time (i.e., 01:00 DST)
+
+# ...
+# Date: Wed, 28 Jan 87 16:56:27 -0100
+# From: Tom Hofmann
+# ...
+#
+# ...the European time rules are...standardized since 1981, when
+# most European coun[tr]ies started DST. Before that year, only
+# a few countries (UK, France, Italy) had DST, each according
+# to own national rules. In 1981, however, DST started on
+# 'Apr firstSun', and not on 'Mar lastSun' as in the following
+# years...
+# But also since 1981 there are some more national exceptions
+# than listed in 'europe': Switzerland, for example, joined DST
+# one year later, Denmark ended DST on 'Oct 1' instead of 'Sep
+# lastSun' in 1981---I don't know how they handle now.
+#
+# Finally, DST ist always from 'Apr 1' to 'Oct 1' in the
+# Soviet Union (as far as I know).
+#
+# Tom Hofmann, Scientific Computer Center, CIBA-GEIGY AG,
+# 4002 Basle, Switzerland
+# ...
+
+# ...
+# Date: Wed, 4 Feb 87 22:35:22 +0100
+# From: Dik T. Winter
+# ...
+#
+# The information from Tom Hofmann is (as far as I know) not entirely correct.
+# After a request from chongo at amdahl I tried to retrieve all information
+# about DST in Europe. I was able to find all from about 1969.
+#
+# ...standardization on DST in Europe started in about 1977 with switches on
+# first Sunday in April and last Sunday in September...
+# In 1981 UK joined Europe insofar that
+# the starting day for both shifted to last Sunday in March. And from 1982
+# the whole of Europe used DST, with switch dates April 1 and October 1 in
+# the Sov[i]et Union. In 1985 the SU reverted to standard Europe[a]n switch
+# dates...
+#
+# It should also be remembered that time-zones are not constants; e.g.
+# Portugal switched in 1976 from MET (or CET) to WET with DST...
+# Note also that though there were rules for switch dates not
+# all countries abided to these dates, and many individual deviations
+# occurred, though not since 1982 I believe. Another note: it is always
+# assumed that DST is 1 hour ahead of normal time, this need not be the
+# case; at least in the Netherlands there have been times when DST was 2 hours
+# in advance of normal time.
+#
+# ...
+# dik t. winter, cwi, amsterdam, nederland
+# ...
+
+# From Bob Devine (1988-01-28):
+# ...
+# Greece: Last Sunday in April to last Sunday in September (iffy on dates).
+# Since 1978. Change at midnight.
+# ...
+# Monaco: has same DST as France.
+# ...
diff --git a/tools/zoneinfo/tzdata2008h/factory b/tools/zoneinfo/tzdata2008h/factory
new file mode 100644
index 0000000..946063c
--- /dev/null
+++ b/tools/zoneinfo/tzdata2008h/factory
@@ -0,0 +1,8 @@
+# @(#)factory 8.1
+
+# For companies who don't want to put time zone specification in
+# their installation procedures. When users run date, they'll get the message.
+# Also useful for the "comp.sources" version.
+
+# Zone NAME GMTOFF RULES FORMAT
+Zone Factory 0 - "Local time zone must be set--see zic manual page"
diff --git a/tools/zoneinfo/tzdata2008h/iso3166.tab b/tools/zoneinfo/tzdata2008h/iso3166.tab
new file mode 100644
index 0000000..8d62399
--- /dev/null
+++ b/tools/zoneinfo/tzdata2008h/iso3166.tab
@@ -0,0 +1,269 @@
+# ISO 3166 alpha-2 country codes
+#
+# @(#)iso3166.tab 8.5
+#
+# From Paul Eggert (2006-09-27):
+#
+# This file contains a table with the following columns:
+# 1. ISO 3166-1 alpha-2 country code, current as of
+# ISO 3166-1 Newsletter VI-1 (2007-09-21). See:
+# <a href="http://www.iso.org/iso/en/prods-services/iso3166ma/index.html">
+# ISO 3166 Maintenance agency (ISO 3166/MA)
+# </a>.
+# 2. The usual English name for the country,
+# chosen so that alphabetic sorting of subsets produces helpful lists.
+# This is not the same as the English name in the ISO 3166 tables.
+#
+# Columns are separated by a single tab.
+# The table is sorted by country code.
+#
+# Lines beginning with `#' are comments.
+#
+#country-
+#code country name
+AD Andorra
+AE United Arab Emirates
+AF Afghanistan
+AG Antigua & Barbuda
+AI Anguilla
+AL Albania
+AM Armenia
+AN Netherlands Antilles
+AO Angola
+AQ Antarctica
+AR Argentina
+AS Samoa (American)
+AT Austria
+AU Australia
+AW Aruba
+AX Aaland Islands
+AZ Azerbaijan
+BA Bosnia & Herzegovina
+BB Barbados
+BD Bangladesh
+BE Belgium
+BF Burkina Faso
+BG Bulgaria
+BH Bahrain
+BI Burundi
+BJ Benin
+BL St Barthelemy
+BM Bermuda
+BN Brunei
+BO Bolivia
+BR Brazil
+BS Bahamas
+BT Bhutan
+BV Bouvet Island
+BW Botswana
+BY Belarus
+BZ Belize
+CA Canada
+CC Cocos (Keeling) Islands
+CD Congo (Dem. Rep.)
+CF Central African Rep.
+CG Congo (Rep.)
+CH Switzerland
+CI Cote d'Ivoire
+CK Cook Islands
+CL Chile
+CM Cameroon
+CN China
+CO Colombia
+CR Costa Rica
+CU Cuba
+CV Cape Verde
+CX Christmas Island
+CY Cyprus
+CZ Czech Republic
+DE Germany
+DJ Djibouti
+DK Denmark
+DM Dominica
+DO Dominican Republic
+DZ Algeria
+EC Ecuador
+EE Estonia
+EG Egypt
+EH Western Sahara
+ER Eritrea
+ES Spain
+ET Ethiopia
+FI Finland
+FJ Fiji
+FK Falkland Islands
+FM Micronesia
+FO Faroe Islands
+FR France
+GA Gabon
+GB Britain (UK)
+GD Grenada
+GE Georgia
+GF French Guiana
+GG Guernsey
+GH Ghana
+GI Gibraltar
+GL Greenland
+GM Gambia
+GN Guinea
+GP Guadeloupe
+GQ Equatorial Guinea
+GR Greece
+GS South Georgia & the South Sandwich Islands
+GT Guatemala
+GU Guam
+GW Guinea-Bissau
+GY Guyana
+HK Hong Kong
+HM Heard Island & McDonald Islands
+HN Honduras
+HR Croatia
+HT Haiti
+HU Hungary
+ID Indonesia
+IE Ireland
+IL Israel
+IM Isle of Man
+IN India
+IO British Indian Ocean Territory
+IQ Iraq
+IR Iran
+IS Iceland
+IT Italy
+JE Jersey
+JM Jamaica
+JO Jordan
+JP Japan
+KE Kenya
+KG Kyrgyzstan
+KH Cambodia
+KI Kiribati
+KM Comoros
+KN St Kitts & Nevis
+KP Korea (North)
+KR Korea (South)
+KW Kuwait
+KY Cayman Islands
+KZ Kazakhstan
+LA Laos
+LB Lebanon
+LC St Lucia
+LI Liechtenstein
+LK Sri Lanka
+LR Liberia
+LS Lesotho
+LT Lithuania
+LU Luxembourg
+LV Latvia
+LY Libya
+MA Morocco
+MC Monaco
+MD Moldova
+ME Montenegro
+MF St Martin (French part)
+MG Madagascar
+MH Marshall Islands
+MK Macedonia
+ML Mali
+MM Myanmar (Burma)
+MN Mongolia
+MO Macau
+MP Northern Mariana Islands
+MQ Martinique
+MR Mauritania
+MS Montserrat
+MT Malta
+MU Mauritius
+MV Maldives
+MW Malawi
+MX Mexico
+MY Malaysia
+MZ Mozambique
+NA Namibia
+NC New Caledonia
+NE Niger
+NF Norfolk Island
+NG Nigeria
+NI Nicaragua
+NL Netherlands
+NO Norway
+NP Nepal
+NR Nauru
+NU Niue
+NZ New Zealand
+OM Oman
+PA Panama
+PE Peru
+PF French Polynesia
+PG Papua New Guinea
+PH Philippines
+PK Pakistan
+PL Poland
+PM St Pierre & Miquelon
+PN Pitcairn
+PR Puerto Rico
+PS Palestine
+PT Portugal
+PW Palau
+PY Paraguay
+QA Qatar
+RE Reunion
+RO Romania
+RS Serbia
+RU Russia
+RW Rwanda
+SA Saudi Arabia
+SB Solomon Islands
+SC Seychelles
+SD Sudan
+SE Sweden
+SG Singapore
+SH St Helena
+SI Slovenia
+SJ Svalbard & Jan Mayen
+SK Slovakia
+SL Sierra Leone
+SM San Marino
+SN Senegal
+SO Somalia
+SR Suriname
+ST Sao Tome & Principe
+SV El Salvador
+SY Syria
+SZ Swaziland
+TC Turks & Caicos Is
+TD Chad
+TF French Southern & Antarctic Lands
+TG Togo
+TH Thailand
+TJ Tajikistan
+TK Tokelau
+TL East Timor
+TM Turkmenistan
+TN Tunisia
+TO Tonga
+TR Turkey
+TT Trinidad & Tobago
+TV Tuvalu
+TW Taiwan
+TZ Tanzania
+UA Ukraine
+UG Uganda
+UM US minor outlying islands
+US United States
+UY Uruguay
+UZ Uzbekistan
+VA Vatican City
+VC St Vincent
+VE Venezuela
+VG Virgin Islands (UK)
+VI Virgin Islands (US)
+VN Vietnam
+VU Vanuatu
+WF Wallis & Futuna
+WS Samoa (western)
+YE Yemen
+YT Mayotte
+ZA South Africa
+ZM Zambia
+ZW Zimbabwe
diff --git a/tools/zoneinfo/tzdata2008h/leapseconds b/tools/zoneinfo/tzdata2008h/leapseconds
new file mode 100644
index 0000000..a2f4f0b
--- /dev/null
+++ b/tools/zoneinfo/tzdata2008h/leapseconds
@@ -0,0 +1,92 @@
+# @(#)leapseconds 8.6
+
+# Allowance for leapseconds added to each timezone file.
+
+# The International Earth Rotation Service periodically uses leap seconds
+# to keep UTC to within 0.9 s of UT1
+# (which measures the true angular orientation of the earth in space); see
+# Terry J Quinn, The BIPM and the accurate measure of time,
+# Proc IEEE 79, 7 (July 1991), 894-905.
+# There were no leap seconds before 1972, because the official mechanism
+# accounting for the discrepancy between atomic time and the earth's rotation
+# did not exist until the early 1970s.
+
+# The correction (+ or -) is made at the given time, so lines
+# will typically look like:
+# Leap YEAR MON DAY 23:59:60 + R/S
+# or
+# Leap YEAR MON DAY 23:59:59 - R/S
+
+# If the leapsecond is Rolling (R) the given time is local time
+# If the leapsecond is Stationary (S) the given time is UTC
+
+# Leap YEAR MONTH DAY HH:MM:SS CORR R/S
+Leap 1972 Jun 30 23:59:60 + S
+Leap 1972 Dec 31 23:59:60 + S
+Leap 1973 Dec 31 23:59:60 + S
+Leap 1974 Dec 31 23:59:60 + S
+Leap 1975 Dec 31 23:59:60 + S
+Leap 1976 Dec 31 23:59:60 + S
+Leap 1977 Dec 31 23:59:60 + S
+Leap 1978 Dec 31 23:59:60 + S
+Leap 1979 Dec 31 23:59:60 + S
+Leap 1981 Jun 30 23:59:60 + S
+Leap 1982 Jun 30 23:59:60 + S
+Leap 1983 Jun 30 23:59:60 + S
+Leap 1985 Jun 30 23:59:60 + S
+Leap 1987 Dec 31 23:59:60 + S
+Leap 1989 Dec 31 23:59:60 + S
+Leap 1990 Dec 31 23:59:60 + S
+Leap 1992 Jun 30 23:59:60 + S
+Leap 1993 Jun 30 23:59:60 + S
+Leap 1994 Jun 30 23:59:60 + S
+Leap 1995 Dec 31 23:59:60 + S
+Leap 1997 Jun 30 23:59:60 + S
+Leap 1998 Dec 31 23:59:60 + S
+Leap 2005 Dec 31 23:59:60 + S
+Leap 2008 Dec 31 23:59:60 + S
+
+# INTERNATIONAL EARTH ROTATION AND REFERENCE SYSTEMS SERVICE (IERS)
+#
+# SERVICE INTERNATIONAL DE LA ROTATION TERRESTRE ET DES SYSTEMES DE REFERENCE
+#
+# SERVICE DE LA ROTATION TERRESTRE
+# OBSERVATOIRE DE PARIS
+# 61, Av. de l'Observatoire 75014 PARIS (France)
+# Tel. : 33 (0) 1 40 51 22 26
+# FAX : 33 (0) 1 40 51 22 91
+# e-mail : services.iers@obspm.fr
+# http://hpiers.obspm.fr/eop-pc
+#
+# Paris, 4 July 2008
+#
+# Bulletin C 36
+#
+# To authorities responsible
+# for the measurement and
+# distribution of time
+#
+# UTC TIME STEP
+# on the 1st of January 2009
+#
+# A positive leap second will be introduced at the end of December 2008.
+# The sequence of dates of the UTC second markers will be:
+#
+# 2008 December 31, 23h 59m 59s
+# 2008 December 31, 23h 59m 60s
+# 2009 January 1, 0h 0m 0s
+#
+# The difference between UTC and the International Atomic Time TAI is:
+#
+# from 2006 January 1, 0h UTC, to 2009 January 1 0h UTC : UTC-TAI = - 33s
+# from 2009 January 1, 0h UTC, until further notice : UTC-TAI = - 34s
+#
+# Leap seconds can be introduced in UTC at the end of the months of December
+# or June, depending on the evolution of UT1-TAI. Bulletin C is mailed every
+# six months, either to announce a time step in UTC or to confirm that there
+# will be no time step at the next possible date.
+#
+# Daniel GAMBIS
+# Head
+# Earth Orientation Center of IERS
+# Observatoire de Paris, France
diff --git a/tools/zoneinfo/tzdata2008h/northamerica b/tools/zoneinfo/tzdata2008h/northamerica
new file mode 100644
index 0000000..b8b333c
--- /dev/null
+++ b/tools/zoneinfo/tzdata2008h/northamerica
@@ -0,0 +1,2651 @@
+# @(#)northamerica 8.24
+# <pre>
+
+# also includes Central America and the Caribbean
+
+# This data is by no means authoritative; if you think you know better,
+# go ahead and edit the file (and please send any changes to
+# tz@elsie.nci.nih.gov for general use in the future).
+
+# From Paul Eggert (1999-03-22):
+# A reliable and entertaining source about time zones is
+# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
+
+###############################################################################
+
+# United States
+
+# From Paul Eggert (1999-03-31):
+# Howse writes (pp 121-125) that time zones were invented by
+# Professor Charles Ferdinand Dowd (1825-1904),
+# Principal of Temple Grove Ladies' Seminary (Saratoga Springs, NY).
+# His pamphlet ``A System of National Time for Railroads'' (1870)
+# was the result of his proposals at the Convention of Railroad Trunk Lines
+# in New York City (1869-10). His 1870 proposal was based on Washington, DC,
+# but in 1872-05 he moved the proposed origin to Greenwich.
+# His proposal was adopted by the railroads on 1883-11-18 at 12:00,
+# and the most of the country soon followed suit.
+
+# From Paul Eggert (2005-04-16):
+# That 1883 transition occurred at 12:00 new time, not at 12:00 old time.
+# See p 46 of David Prerau, Seize the daylight, Thunder's Mouth Press (2005).
+
+# From Paul Eggert (2006-03-22):
+# A good source for time zone historical data in the US is
+# Thomas G. Shanks, The American Atlas (5th edition),
+# San Diego: ACS Publications, Inc. (1991).
+# Make sure you have the errata sheet; the book is somewhat useless without it.
+# It is the source for most of the pre-1991 US entries below.
+
+# From Paul Eggert (2001-03-06):
+# Daylight Saving Time was first suggested as a joke by Benjamin Franklin
+# in his whimsical essay ``An Economical Project for Diminishing the Cost
+# of Light'' published in the Journal de Paris (1784-04-26).
+# Not everyone is happy with the results:
+#
+# I don't really care how time is reckoned so long as there is some
+# agreement about it, but I object to being told that I am saving
+# daylight when my reason tells me that I am doing nothing of the kind.
+# I even object to the implication that I am wasting something
+# valuable if I stay in bed after the sun has risen. As an admirer
+# of moonlight I resent the bossy insistence of those who want to
+# reduce my time for enjoying it. At the back of the Daylight Saving
+# scheme I detect the bony, blue-fingered hand of Puritanism, eager
+# to push people into bed earlier, and get them up earlier, to make
+# them healthy, wealthy and wise in spite of themselves.
+#
+# -- Robertson Davies, The diary of Samuel Marchbanks,
+# Clarke, Irwin (1947), XIX, Sunday
+#
+# For more about the first ten years of DST in the United States, see
+# Robert Garland's <a href="http://www.clpgh.org/exhibit/dst.html">
+# Ten years of daylight saving from the Pittsburgh standpoint
+# (Carnegie Library of Pittsburgh, 1927)</a>.
+#
+# Shanks says that DST was called "War Time" in the US in 1918 and 1919.
+# However, DST was imposed by the Standard Time Act of 1918, which
+# was the first nationwide legal time standard, and apparently
+# time was just called "Standard Time" or "Daylight Saving Time".
+
+# From Arthur David Olson:
+# US Daylight Saving Time ended on the last Sunday of *October* in 1974.
+# See, for example, the front page of the Saturday, 1974-10-26
+# and Sunday, 1974-10-27 editions of the Washington Post.
+
+# From Arthur David Olson:
+# Before the Uniform Time Act of 1966 took effect in 1967, observance of
+# Daylight Saving Time in the US was by local option, except during wartime.
+
+# From Arthur David Olson (2000-09-25):
+# Last night I heard part of a rebroadcast of a 1945 Arch Oboler radio drama.
+# In the introduction, Oboler spoke of "Eastern Peace Time."
+# An AltaVista search turned up
+# <a href="http://rowayton.org/rhs/hstaug45.html">:
+# "When the time is announced over the radio now, it is 'Eastern Peace
+# Time' instead of the old familiar 'Eastern War Time.' Peace is wonderful."
+# </a> (August 1945) by way of confirmation.
+
+# From Joseph Gallant citing
+# George H. Douglas, _The Early Days of Radio Broadcasting_ (1987):
+# At 7 P.M. (Eastern War Time) [on 1945-08-14], the networks were set
+# to switch to London for Attlee's address, but the American people
+# never got to hear his speech live. According to one press account,
+# CBS' Bob Trout was first to announce the word of Japan's surrender,
+# but a few seconds later, NBC, ABC and Mutual also flashed the word
+# of surrender, all of whom interrupting the bells of Big Ben in
+# London which were to precede Mr. Attlee's speech.
+
+# From Paul Eggert (2003-02-09): It was Robert St John, not Bob Trout. From
+# Myrna Oliver's obituary of St John on page B16 of today's Los Angeles Times:
+#
+# ... a war-weary U.S. clung to radios, awaiting word of Japan's surrender.
+# Any announcement from Asia would reach St. John's New York newsroom on a
+# wire service teletype machine, which had prescribed signals for major news.
+# Associated Press, for example, would ring five bells before spewing out
+# typed copy of an important story, and 10 bells for news "of transcendental
+# importance."
+#
+# On Aug. 14, stalling while talking steadily into the NBC networks' open
+# microphone, St. John heard five bells and waited only to hear a sixth bell,
+# before announcing confidently: "Ladies and gentlemen, World War II is over.
+# The Japanese have agreed to our surrender terms."
+#
+# He had scored a 20-second scoop on other broadcasters.
+
+# From Arthur David Olson (2005-08-22):
+# Paul has been careful to use the "US" rules only in those locations
+# that are part of the United States; this reflects the real scope of
+# U.S. government action. So even though the "US" rules have changed
+# in the latest release, other countries won't be affected.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule US 1918 1919 - Mar lastSun 2:00 1:00 D
+Rule US 1918 1919 - Oct lastSun 2:00 0 S
+Rule US 1942 only - Feb 9 2:00 1:00 W # War
+Rule US 1945 only - Aug 14 23:00u 1:00 P # Peace
+Rule US 1945 only - Sep 30 2:00 0 S
+Rule US 1967 2006 - Oct lastSun 2:00 0 S
+Rule US 1967 1973 - Apr lastSun 2:00 1:00 D
+Rule US 1974 only - Jan 6 2:00 1:00 D
+Rule US 1975 only - Feb 23 2:00 1:00 D
+Rule US 1976 1986 - Apr lastSun 2:00 1:00 D
+Rule US 1987 2006 - Apr Sun>=1 2:00 1:00 D
+Rule US 2007 max - Mar Sun>=8 2:00 1:00 D
+Rule US 2007 max - Nov Sun>=1 2:00 0 S
+
+# From Arthur David Olson, 2005-12-19
+# We generate the files specified below to guard against old files with
+# obsolete information being left in the time zone binary directory.
+# We limit the list to names that have appeared in previous versions of
+# this time zone package.
+# We do these as separate Zones rather than as Links to avoid problems if
+# a particular place changes whether it observes DST.
+# We put these specifications here in the northamerica file both to
+# increase the chances that they'll actually get compiled and to
+# avoid the need to duplicate the US rules in another file.
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone EST -5:00 - EST
+Zone MST -7:00 - MST
+Zone HST -10:00 - HST
+Zone EST5EDT -5:00 US E%sT
+Zone CST6CDT -6:00 US C%sT
+Zone MST7MDT -7:00 US M%sT
+Zone PST8PDT -8:00 US P%sT
+
+# From Bob Devine (1988-01-28):
+# ...Alaska (and Hawaii) had the timezone names changed in 1967.
+# old new
+# Pacific Standard Time(PST) -same-
+# Yukon Standard Time(YST) -same-
+# Central Alaska S.T. (CAT) Alaska-Hawaii St[an]dard Time (AHST)
+# Nome Standard Time (NT) Bering Standard Time (BST)
+#
+# ...Alaska's timezone lines were redrawn in 1983 to give only 2 tz.
+# The YST zone now covers nearly all of the state, AHST just part
+# of the Aleutian islands. No DST.
+
+# From Paul Eggert (1995-12-19):
+# The tables below use `NST', not `NT', for Nome Standard Time.
+# I invented `CAWT' for Central Alaska War Time.
+
+# From U. S. Naval Observatory (1989-01-19):
+# USA EASTERN 5 H BEHIND UTC NEW YORK, WASHINGTON
+# USA EASTERN 4 H BEHIND UTC APR 3 - OCT 30
+# USA CENTRAL 6 H BEHIND UTC CHICAGO, HOUSTON
+# USA CENTRAL 5 H BEHIND UTC APR 3 - OCT 30
+# USA MOUNTAIN 7 H BEHIND UTC DENVER
+# USA MOUNTAIN 6 H BEHIND UTC APR 3 - OCT 30
+# USA PACIFIC 8 H BEHIND UTC L.A., SAN FRANCISCO
+# USA PACIFIC 7 H BEHIND UTC APR 3 - OCT 30
+# USA ALASKA STD 9 H BEHIND UTC MOST OF ALASKA (AKST)
+# USA ALASKA STD 8 H BEHIND UTC APR 3 - OCT 30 (AKDT)
+# USA ALEUTIAN 10 H BEHIND UTC ISLANDS WEST OF 170W
+# USA - " - 9 H BEHIND UTC APR 3 - OCT 30
+# USA HAWAII 10 H BEHIND UTC
+# USA BERING 11 H BEHIND UTC SAMOA, MIDWAY
+
+# From Arthur David Olson (1989-01-21):
+# The above dates are for 1988.
+# Note the "AKST" and "AKDT" abbreviations, the claim that there's
+# no DST in Samoa, and the claim that there is DST in Alaska and the
+# Aleutians.
+
+# From Arthur David Olson (1988-02-13):
+# Legal standard time zone names, from United States Code (1982 Edition and
+# Supplement III), Title 15, Chapter 6, Section 260 and forward. First, names
+# up to 1967-04-01 (when most provisions of the Uniform Time Act of 1966
+# took effect), as explained in sections 263 and 261:
+# (none)
+# United States standard eastern time
+# United States standard mountain time
+# United States standard central time
+# United States standard Pacific time
+# (none)
+# United States standard Alaska time
+# (none)
+# Next, names from 1967-04-01 until 1983-11-30 (the date for
+# public law 98-181):
+# Atlantic standard time
+# eastern standard time
+# central standard time
+# mountain standard time
+# Pacific standard time
+# Yukon standard time
+# Alaska-Hawaii standard time
+# Bering standard time
+# And after 1983-11-30:
+# Atlantic standard time
+# eastern standard time
+# central standard time
+# mountain standard time
+# Pacific standard time
+# Alaska standard time
+# Hawaii-Aleutian standard time
+# Samoa standard time
+# The law doesn't give abbreviations.
+#
+# From Paul Eggert (2000-01-08), following a heads-up from Rives McDow:
+# Public law 106-564 (2000-12-23) introduced the abbreviation
+# "Chamorro Standard Time" for time in Guam and the Northern Marianas.
+# See the file "australasia".
+
+# From Arthur David Olson, 2005-08-09
+# The following was signed into law on 2005-08-08.
+#
+# H.R. 6, Energy Policy Act of 2005, SEC. 110. DAYLIGHT SAVINGS.
+# (a) Amendment- Section 3(a) of the Uniform Time Act of 1966 (15
+# U.S.C. 260a(a)) is amended--
+# (1) by striking `first Sunday of April' and inserting `second
+# Sunday of March'; and
+# (2) by striking `last Sunday of October' and inserting `first
+# Sunday of November'.
+# (b) Effective Date- Subsection (a) shall take effect 1 year after the
+# date of enactment of this Act or March 1, 2007, whichever is later.
+# (c) Report to Congress- Not later than 9 months after the effective
+# date stated in subsection (b), the Secretary shall report to Congress
+# on the impact of this section on energy consumption in the United
+# States.
+# (d) Right to Revert- Congress retains the right to revert the
+# Daylight Saving Time back to the 2005 time schedules once the
+# Department study is complete.
+
+# US eastern time, represented by New York
+
+# Connecticut, Delaware, District of Columbia, most of Florida,
+# Georgia, southeast Indiana (Dearborn and Ohio counties), eastern Kentucky
+# (except America/Kentucky/Louisville below), Maine, Maryland, Massachusetts,
+# New Hampshire, New Jersey, New York, North Carolina, Ohio,
+# Pennsylvania, Rhode Island, South Carolina, eastern Tennessee,
+# Vermont, Virginia, West Virginia
+
+# From Dave Cantor (2004-11-02):
+# Early this summer I had the occasion to visit the Mount Washington
+# Observatory weather station atop (of course!) Mount Washington [, NH]....
+# One of the staff members said that the station was on Eastern Standard Time
+# and didn't change their clocks for Daylight Saving ... so that their
+# reports will always have times which are 5 hours behind UTC.
+
+# From Paul Eggert (2005-08-26):
+# According to today's Huntsville Times
+# <http://www.al.com/news/huntsvilletimes/index.ssf?/base/news/1125047783228320.xml&coll=1>
+# a few towns on Alabama's "eastern border with Georgia, such as Phenix City
+# in Russell County, Lanett in Chambers County and some towns in Lee County,
+# set their watches and clocks on Eastern time." It quotes H.H. "Bubba"
+# Roberts, city administrator in Phenix City. as saying "We are in the Central
+# time zone, but we do go by the Eastern time zone because so many people work
+# in Columbus."
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
+Rule NYC 1920 only - Mar lastSun 2:00 1:00 D
+Rule NYC 1920 only - Oct lastSun 2:00 0 S
+Rule NYC 1921 1966 - Apr lastSun 2:00 1:00 D
+Rule NYC 1921 1954 - Sep lastSun 2:00 0 S
+Rule NYC 1955 1966 - Oct lastSun 2:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/New_York -4:56:02 - LMT 1883 Nov 18 12:03:58
+ -5:00 US E%sT 1920
+ -5:00 NYC E%sT 1942
+ -5:00 US E%sT 1946
+ -5:00 NYC E%sT 1967
+ -5:00 US E%sT
+
+# US central time, represented by Chicago
+
+# Alabama, Arkansas, Florida panhandle (Bay, Calhoun, Escambia,
+# Gulf, Holmes, Jackson, Okaloosa, Santa Rosa, Walton, and
+# Washington counties), Illinois, western Indiana
+# (Gibson, Jasper, Lake, LaPorte, Newton, Porter, Posey, Spencer,
+# Vanderburgh, and Warrick counties), Iowa, most of Kansas, western
+# Kentucky, Louisiana, Minnesota, Mississippi, Missouri, eastern
+# Nebraska, eastern North Dakota, Oklahoma, eastern South Dakota,
+# western Tennessee, most of Texas, Wisconsin
+
+# From Larry M. Smith (2006-04-26) re Wisconsin:
+# http://www.legis.state.wi.us/statutes/Stat0175.pdf ...
+# is currently enforced at the 01:00 time of change. Because the local
+# "bar time" in the state corresponds to 02:00, a number of citations
+# are issued for the "sale of class 'B' alcohol after prohibited
+# hours" within the deviated hour of this change every year....
+#
+# From Douglas R. Bomberg (2007-03-12):
+# Wisconsin has enacted (nearly eleventh-hour) legislation to get WI
+# Statue 175 closer in synch with the US Congress' intent....
+# http://www.legis.state.wi.us/2007/data/acts/07Act3.pdf
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
+Rule Chicago 1920 only - Jun 13 2:00 1:00 D
+Rule Chicago 1920 1921 - Oct lastSun 2:00 0 S
+Rule Chicago 1921 only - Mar lastSun 2:00 1:00 D
+Rule Chicago 1922 1966 - Apr lastSun 2:00 1:00 D
+Rule Chicago 1922 1954 - Sep lastSun 2:00 0 S
+Rule Chicago 1955 1966 - Oct lastSun 2:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Chicago -5:50:36 - LMT 1883 Nov 18 12:09:24
+ -6:00 US C%sT 1920
+ -6:00 Chicago C%sT 1936 Mar 1 2:00
+ -5:00 - EST 1936 Nov 15 2:00
+ -6:00 Chicago C%sT 1942
+ -6:00 US C%sT 1946
+ -6:00 Chicago C%sT 1967
+ -6:00 US C%sT
+# Oliver County, ND switched from mountain to central time on 1992-10-25.
+Zone America/North_Dakota/Center -6:45:12 - LMT 1883 Nov 18 12:14:48
+ -7:00 US M%sT 1992 Oct 25 02:00
+ -6:00 US C%sT
+# Morton County, ND, switched from mountain to central time on
+# 2003-10-26, except for the area around Mandan which was already central time.
+# See <http://dmses.dot.gov/docimages/p63/135818.pdf>.
+# Officially this switch also included part of Sioux County, and
+# Jones, Mellette, and Todd Counties in South Dakota;
+# but in practice these other counties were already observing central time.
+# See <http://www.epa.gov/fedrgstr/EPA-IMPACT/2003/October/Day-28/i27056.htm>.
+Zone America/North_Dakota/New_Salem -6:45:39 - LMT 1883 Nov 18 12:14:21
+ -7:00 US M%sT 2003 Oct 26 02:00
+ -6:00 US C%sT
+
+# US mountain time, represented by Denver
+#
+# Colorado, far western Kansas, Montana, western
+# Nebraska, Nevada border (Jackpot, Owyhee, and Mountain City),
+# New Mexico, southwestern North Dakota,
+# western South Dakota, far western Texas (El Paso County, Hudspeth County,
+# and Pine Springs and Nickel Creek in Culberson County), Utah, Wyoming
+#
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
+Rule Denver 1920 1921 - Mar lastSun 2:00 1:00 D
+Rule Denver 1920 only - Oct lastSun 2:00 0 S
+Rule Denver 1921 only - May 22 2:00 0 S
+Rule Denver 1965 1966 - Apr lastSun 2:00 1:00 D
+Rule Denver 1965 1966 - Oct lastSun 2:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Denver -6:59:56 - LMT 1883 Nov 18 12:00:04
+ -7:00 US M%sT 1920
+ -7:00 Denver M%sT 1942
+ -7:00 US M%sT 1946
+ -7:00 Denver M%sT 1967
+ -7:00 US M%sT
+
+# US Pacific time, represented by Los Angeles
+#
+# California, northern Idaho (Benewah, Bonner, Boundary, Clearwater,
+# Idaho, Kootenai, Latah, Lewis, Nez Perce, and Shoshone counties,
+# and the northern three-quarters of Idaho county),
+# most of Nevada, most of Oregon, and Washington
+#
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
+Rule CA 1948 only - Mar 14 2:00 1:00 D
+Rule CA 1949 only - Jan 1 2:00 0 S
+Rule CA 1950 1966 - Apr lastSun 2:00 1:00 D
+Rule CA 1950 1961 - Sep lastSun 2:00 0 S
+Rule CA 1962 1966 - Oct lastSun 2:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Los_Angeles -7:52:58 - LMT 1883 Nov 18 12:07:02
+ -8:00 US P%sT 1946
+ -8:00 CA P%sT 1967
+ -8:00 US P%sT
+
+# Alaska
+# AK%sT is the modern abbreviation for -9:00 per USNO.
+#
+# From Paul Eggert (2001-05-30):
+# Howse writes that Alaska switched from the Julian to the Gregorian calendar,
+# and from east-of-GMT to west-of-GMT days, when the US bought it from Russia.
+# This was on 1867-10-18, a Friday; the previous day was 1867-10-06 Julian,
+# also a Friday. Include only the time zone part of this transition,
+# ignoring the switch from Julian to Gregorian, since we can't represent
+# the Julian calendar.
+#
+# As far as we know, none of the exact locations mentioned below were
+# permanently inhabited in 1867 by anyone using either calendar.
+# (Yakutat was colonized by the Russians in 1799, but the settlement
+# was destroyed in 1805 by a Yakutat-kon war party.) However, there
+# were nearby inhabitants in some cases and for our purposes perhaps
+# it's best to simply use the official transition.
+#
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Juneau 15:02:19 - LMT 1867 Oct 18
+ -8:57:41 - LMT 1900 Aug 20 12:00
+ -8:00 - PST 1942
+ -8:00 US P%sT 1946
+ -8:00 - PST 1969
+ -8:00 US P%sT 1983 Oct 30 2:00
+ -9:00 US Y%sT 1983 Nov 30
+ -9:00 US AK%sT
+Zone America/Yakutat 14:41:05 - LMT 1867 Oct 18
+ -9:18:55 - LMT 1900 Aug 20 12:00
+ -9:00 - YST 1942
+ -9:00 US Y%sT 1946
+ -9:00 - YST 1969
+ -9:00 US Y%sT 1983 Nov 30
+ -9:00 US AK%sT
+Zone America/Anchorage 14:00:24 - LMT 1867 Oct 18
+ -9:59:36 - LMT 1900 Aug 20 12:00
+ -10:00 - CAT 1942
+ -10:00 US CAT/CAWT 1945 Aug 14 23:00u
+ -10:00 US CAT/CAPT 1946 # Peace
+ -10:00 - CAT 1967 Apr
+ -10:00 - AHST 1969
+ -10:00 US AH%sT 1983 Oct 30 2:00
+ -9:00 US Y%sT 1983 Nov 30
+ -9:00 US AK%sT
+Zone America/Nome 12:58:21 - LMT 1867 Oct 18
+ -11:01:38 - LMT 1900 Aug 20 12:00
+ -11:00 - NST 1942
+ -11:00 US N%sT 1946
+ -11:00 - NST 1967 Apr
+ -11:00 - BST 1969
+ -11:00 US B%sT 1983 Oct 30 2:00
+ -9:00 US Y%sT 1983 Nov 30
+ -9:00 US AK%sT
+Zone America/Adak 12:13:21 - LMT 1867 Oct 18
+ -11:46:38 - LMT 1900 Aug 20 12:00
+ -11:00 - NST 1942
+ -11:00 US N%sT 1946
+ -11:00 - NST 1967 Apr
+ -11:00 - BST 1969
+ -11:00 US B%sT 1983 Oct 30 2:00
+ -10:00 US AH%sT 1983 Nov 30
+ -10:00 US HA%sT
+# The following switches don't quite make our 1970 cutoff.
+#
+# Shanks writes that part of southwest Alaska (e.g. Aniak)
+# switched from -11:00 to -10:00 on 1968-09-22 at 02:00,
+# and another part (e.g. Akiak) made the same switch five weeks later.
+#
+# From David Flater (2004-11-09):
+# In e-mail, 2004-11-02, Ray Hudson, historian/liaison to the Unalaska
+# Historic Preservation Commission, provided this information, which
+# suggests that Unalaska deviated from statutory time from early 1967
+# possibly until 1983:
+#
+# Minutes of the Unalaska City Council Meeting, January 10, 1967:
+# "Except for St. Paul and Akutan, Unalaska is the only important
+# location not on Alaska Standard Time. The following resolution was
+# made by William Robinson and seconded by Henry Swanson: Be it
+# resolved that the City of Unalaska hereby goes to Alaska Standard
+# Time as of midnight Friday, January 13, 1967 (1 A.M. Saturday,
+# January 14, Alaska Standard Time.) This resolution was passed with
+# three votes for and one against."
+
+# Hawaii
+#
+# From Arthur David Olson:
+# And then there's Hawaii.
+# DST was observed for one day in 1933;
+# standard time was changed by half an hour in 1947;
+# it's always standard as of 1986.
+#
+# From Paul Eggert:
+# Shanks says the 1933 experiment lasted for three weeks. Go with Shanks.
+#
+Zone Pacific/Honolulu -10:31:26 - LMT 1900 Jan 1 12:00
+ -10:30 - HST 1933 Apr 30 2:00
+ -10:30 1:00 HDT 1933 May 21 2:00
+ -10:30 US H%sT 1947 Jun 8 2:00
+ -10:00 - HST
+
+# Now we turn to US areas that have diverged from the consensus since 1970.
+
+# Arizona mostly uses MST.
+
+# From Paul Eggert (2002-10-20):
+#
+# The information in the rest of this paragraph is derived from the
+# <a href="http://www.dlapr.lib.az.us/links/daylight.htm">
+# Daylight Saving Time web page (2002-01-23)</a> maintained by the
+# Arizona State Library, Archives and Public Records.
+# Between 1944-01-01 and 1944-04-01 the State of Arizona used standard
+# time, but by federal law railroads, airlines, bus lines, military
+# personnel, and some engaged in interstate commerce continued to
+# observe war (i.e., daylight saving) time. The 1944-03-17 Phoenix
+# Gazette says that was the date the law changed, and that 04-01 was
+# the date the state's clocks would change. In 1945 the State of
+# Arizona used standard time all year, again with exceptions only as
+# mandated by federal law. Arizona observed DST in 1967, but Arizona
+# Laws 1968, ch. 183 (effective 1968-03-21) repealed DST.
+#
+# Shanks says the 1944 experiment came to an end on 1944-03-17.
+# Go with the Arizona State Library instead.
+
+Zone America/Phoenix -7:28:18 - LMT 1883 Nov 18 11:31:42
+ -7:00 US M%sT 1944 Jan 1 00:01
+ -7:00 - MST 1944 Apr 1 00:01
+ -7:00 US M%sT 1944 Oct 1 00:01
+ -7:00 - MST 1967
+ -7:00 US M%sT 1968 Mar 21
+ -7:00 - MST
+# From Arthur David Olson (1988-02-13):
+# A writer from the Inter Tribal Council of Arizona, Inc.,
+# notes in private correspondence dated 1987-12-28 that "Presently, only the
+# Navajo Nation participates in the Daylight Saving Time policy, due to its
+# large size and location in three states." (The "only" means that other
+# tribal nations don't use DST.)
+
+Link America/Denver America/Shiprock
+
+# Southern Idaho (Ada, Adams, Bannock, Bear Lake, Bingham, Blaine,
+# Boise, Bonneville, Butte, Camas, Canyon, Caribou, Cassia, Clark,
+# Custer, Elmore, Franklin, Fremont, Gem, Gooding, Jefferson, Jerome,
+# Lemhi, Lincoln, Madison, Minidoka, Oneida, Owyhee, Payette, Power,
+# Teton, Twin Falls, Valley, Washington counties, and the southern
+# quarter of Idaho county) and eastern Oregon (most of Malheur County)
+# switched four weeks late in 1974.
+#
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Boise -7:44:49 - LMT 1883 Nov 18 12:15:11
+ -8:00 US P%sT 1923 May 13 2:00
+ -7:00 US M%sT 1974
+ -7:00 - MST 1974 Feb 3 2:00
+ -7:00 US M%sT
+
+# Indiana
+#
+# For a map of Indiana's time zone regions, see:
+# <a href="http://www.mccsc.edu/time.html">
+# What time is it in Indiana?
+# </a> (2006-03-01)
+#
+# From Paul Eggert (2007-08-17):
+# Since 1970, most of Indiana has been like America/Indiana/Indianapolis,
+# with the following exceptions:
+#
+# - Gibson, Jasper, Lake, LaPorte, Newton, Porter, Posey, Spencer,
+# Vandenburgh, and Warrick counties have been like America/Chicago.
+#
+# - Dearborn and Ohio counties have been like America/New_York.
+#
+# - Clark, Floyd, and Harrison counties have been like
+# America/Kentucky/Louisville.
+#
+# - Crawford, Daviess, Dubois, Knox, Martin, Perry, Pike, Pulaski, Starke,
+# and Switzerland counties have their own time zone histories as noted below.
+#
+# Shanks partitioned Indiana into 345 regions, each with its own time history,
+# and wrote ``Even newspaper reports present contradictory information.''
+# Those Hoosiers! Such a flighty and changeable people!
+# Fortunately, most of the complexity occurred before our cutoff date of 1970.
+#
+# Other than Indianapolis, the Indiana place names are so nondescript
+# that they would be ambiguous if we left them at the `America' level.
+# So we reluctantly put them all in a subdirectory `America/Indiana'.
+
+# From Paul Eggert (2005-08-16):
+# http://www.mccsc.edu/time.html says that Indiana will use DST starting 2006.
+
+# From Nathan Stratton Treadway (2006-03-30):
+# http://www.dot.gov/affairs/dot0406.htm [3705 B]
+# From Deborah Goldsmith (2006-01-18):
+# http://dmses.dot.gov/docimages/pdf95/382329_web.pdf [2.9 MB]
+# From Paul Eggert (2006-01-20):
+# It says "DOT is relocating the time zone boundary in Indiana to move Starke,
+# Pulaski, Knox, Daviess, Martin, Pike, Dubois, and Perry Counties from the
+# Eastern Time Zone to the Central Time Zone.... The effective date of
+# this rule is 2:OO a.m. EST Sunday, April 2, 2006, which is the
+# changeover date from standard time to Daylight Saving Time."
+# Strictly speaking, this means the affected counties will change their
+# clocks twice that night, but this obviously is in error. The intent
+# is that 01:59:59 EST be followed by 02:00:00 CDT.
+
+# From Gwillim Law (2007-02-10):
+# The Associated Press has been reporting that Pulaski County, Indiana is
+# going to switch from Central to Eastern Time on March 11, 2007....
+# http://www.indystar.com/apps/pbcs.dll/article?AID=/20070207/LOCAL190108/702070524/0/LOCAL
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
+Rule Indianapolis 1941 only - Jun 22 2:00 1:00 D
+Rule Indianapolis 1941 1954 - Sep lastSun 2:00 0 S
+Rule Indianapolis 1946 1954 - Apr lastSun 2:00 1:00 D
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Indiana/Indianapolis -5:44:38 - LMT 1883 Nov 18 12:15:22
+ -6:00 US C%sT 1920
+ -6:00 Indianapolis C%sT 1942
+ -6:00 US C%sT 1946
+ -6:00 Indianapolis C%sT 1955 Apr 24 2:00
+ -5:00 - EST 1957 Sep 29 2:00
+ -6:00 - CST 1958 Apr 27 2:00
+ -5:00 - EST 1969
+ -5:00 US E%sT 1971
+ -5:00 - EST 2006
+ -5:00 US E%sT
+#
+# Eastern Crawford County, Indiana, left its clocks alone in 1974,
+# as well as from 1976 through 2005.
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
+Rule Marengo 1951 only - Apr lastSun 2:00 1:00 D
+Rule Marengo 1951 only - Sep lastSun 2:00 0 S
+Rule Marengo 1954 1960 - Apr lastSun 2:00 1:00 D
+Rule Marengo 1954 1960 - Sep lastSun 2:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Indiana/Marengo -5:45:23 - LMT 1883 Nov 18 12:14:37
+ -6:00 US C%sT 1951
+ -6:00 Marengo C%sT 1961 Apr 30 2:00
+ -5:00 - EST 1969
+ -5:00 US E%sT 1974 Jan 6 2:00
+ -6:00 1:00 CDT 1974 Oct 27 2:00
+ -5:00 US E%sT 1976
+ -5:00 - EST 2006
+ -5:00 US E%sT
+#
+# Daviess, Dubois, Knox, and Martin Counties, Indiana,
+# switched from eastern to central time in April 2006, then switched back
+# in November 2007.
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
+Rule Vincennes 1946 only - Apr lastSun 2:00 1:00 D
+Rule Vincennes 1946 only - Sep lastSun 2:00 0 S
+Rule Vincennes 1953 1954 - Apr lastSun 2:00 1:00 D
+Rule Vincennes 1953 1959 - Sep lastSun 2:00 0 S
+Rule Vincennes 1955 only - May 1 0:00 1:00 D
+Rule Vincennes 1956 1963 - Apr lastSun 2:00 1:00 D
+Rule Vincennes 1960 only - Oct lastSun 2:00 0 S
+Rule Vincennes 1961 only - Sep lastSun 2:00 0 S
+Rule Vincennes 1962 1963 - Oct lastSun 2:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Indiana/Vincennes -5:50:07 - LMT 1883 Nov 18 12:09:53
+ -6:00 US C%sT 1946
+ -6:00 Vincennes C%sT 1964 Apr 26 2:00
+ -5:00 - EST 1969
+ -5:00 US E%sT 1971
+ -5:00 - EST 2006 Apr 2 2:00
+ -6:00 US C%sT 2007 Nov 4 2:00
+ -5:00 US E%sT
+#
+# Perry County, Indiana, switched from eastern to central time in April 2006.
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
+Rule Perry 1946 only - Apr lastSun 2:00 1:00 D
+Rule Perry 1946 only - Sep lastSun 2:00 0 S
+Rule Perry 1953 1954 - Apr lastSun 2:00 1:00 D
+Rule Perry 1953 1959 - Sep lastSun 2:00 0 S
+Rule Perry 1955 only - May 1 0:00 1:00 D
+Rule Perry 1956 1963 - Apr lastSun 2:00 1:00 D
+Rule Perry 1960 only - Oct lastSun 2:00 0 S
+Rule Perry 1961 only - Sep lastSun 2:00 0 S
+Rule Perry 1962 1963 - Oct lastSun 2:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Indiana/Tell_City -5:47:03 - LMT 1883 Nov 18 12:12:57
+ -6:00 US C%sT 1946
+ -6:00 Perry C%sT 1964 Apr 26 2:00
+ -5:00 - EST 1969
+ -5:00 US E%sT 1971
+ -5:00 - EST 2006 Apr 2 2:00
+ -6:00 US C%sT
+#
+# Pike County, Indiana moved from central to eastern time in 1977,
+# then switched back in 2006, then switched back again in 2007.
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
+Rule Pike 1955 only - May 1 0:00 1:00 D
+Rule Pike 1955 1960 - Sep lastSun 2:00 0 S
+Rule Pike 1956 1964 - Apr lastSun 2:00 1:00 D
+Rule Pike 1961 1964 - Oct lastSun 2:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Indiana/Petersburg -5:49:07 - LMT 1883 Nov 18 12:10:53
+ -6:00 US C%sT 1955
+ -6:00 Pike C%sT 1965 Apr 25 2:00
+ -5:00 - EST 1966 Oct 30 2:00
+ -6:00 US C%sT 1977 Oct 30 2:00
+ -5:00 - EST 2006 Apr 2 2:00
+ -6:00 US C%sT 2007 Nov 4 2:00
+ -5:00 US E%sT
+#
+# Starke County, Indiana moved from central to eastern time in 1991,
+# then switched back in 2006.
+# From Arthur David Olson (1991-10-28):
+# An article on page A3 of the Sunday, 1991-10-27 Washington Post
+# notes that Starke County switched from Central time to Eastern time as of
+# 1991-10-27.
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
+Rule Starke 1947 1961 - Apr lastSun 2:00 1:00 D
+Rule Starke 1947 1954 - Sep lastSun 2:00 0 S
+Rule Starke 1955 1956 - Oct lastSun 2:00 0 S
+Rule Starke 1957 1958 - Sep lastSun 2:00 0 S
+Rule Starke 1959 1961 - Oct lastSun 2:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Indiana/Knox -5:46:30 - LMT 1883 Nov 18 12:13:30
+ -6:00 US C%sT 1947
+ -6:00 Starke C%sT 1962 Apr 29 2:00
+ -5:00 - EST 1963 Oct 27 2:00
+ -6:00 US C%sT 1991 Oct 27 2:00
+ -5:00 - EST 2006 Apr 2 2:00
+ -6:00 US C%sT
+#
+# Pulaski County, Indiana, switched from eastern to central time in
+# April 2006 and then switched back in March 2007.
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
+Rule Pulaski 1946 1960 - Apr lastSun 2:00 1:00 D
+Rule Pulaski 1946 1954 - Sep lastSun 2:00 0 S
+Rule Pulaski 1955 1956 - Oct lastSun 2:00 0 S
+Rule Pulaski 1957 1960 - Sep lastSun 2:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Indiana/Winamac -5:46:25 - LMT 1883 Nov 18 12:13:35
+ -6:00 US C%sT 1946
+ -6:00 Pulaski C%sT 1961 Apr 30 2:00
+ -5:00 - EST 1969
+ -5:00 US E%sT 1971
+ -5:00 - EST 2006 Apr 2 2:00
+ -6:00 US C%sT 2007 Mar 11 2:00
+ -5:00 US E%sT
+#
+# Switzerland County, Indiana, did not observe DST from 1973 through 2005.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Indiana/Vevay -5:40:16 - LMT 1883 Nov 18 12:19:44
+ -6:00 US C%sT 1954 Apr 25 2:00
+ -5:00 - EST 1969
+ -5:00 US E%sT 1973
+ -5:00 - EST 2006
+ -5:00 US E%sT
+
+# Part of Kentucky left its clocks alone in 1974.
+# This also includes Clark, Floyd, and Harrison counties in Indiana.
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
+Rule Louisville 1921 only - May 1 2:00 1:00 D
+Rule Louisville 1921 only - Sep 1 2:00 0 S
+Rule Louisville 1941 1961 - Apr lastSun 2:00 1:00 D
+Rule Louisville 1941 only - Sep lastSun 2:00 0 S
+Rule Louisville 1946 only - Jun 2 2:00 0 S
+Rule Louisville 1950 1955 - Sep lastSun 2:00 0 S
+Rule Louisville 1956 1960 - Oct lastSun 2:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Kentucky/Louisville -5:43:02 - LMT 1883 Nov 18 12:16:58
+ -6:00 US C%sT 1921
+ -6:00 Louisville C%sT 1942
+ -6:00 US C%sT 1946
+ -6:00 Louisville C%sT 1961 Jul 23 2:00
+ -5:00 - EST 1968
+ -5:00 US E%sT 1974 Jan 6 2:00
+ -6:00 1:00 CDT 1974 Oct 27 2:00
+ -5:00 US E%sT
+#
+# Wayne County, Kentucky
+#
+# From
+# <a href="http://www.lake-cumberland.com/life/archive/news990129time.shtml">
+# Lake Cumberland LIFE
+# </a> (1999-01-29) via WKYM-101.7:
+# Clinton County has joined Wayne County in asking the DoT to change from
+# the Central to the Eastern time zone.... The Wayne County government made
+# the same request in December. And while Russell County officials have not
+# taken action, the majority of respondents to a poll conducted there in
+# August indicated they would like to change to "fast time" also.
+# The three Lake Cumberland counties are the farthest east of any U.S.
+# location in the Central time zone.
+#
+# From Rich Wales (2000-08-29):
+# After prolonged debate, and despite continuing deep differences of opinion,
+# Wayne County (central Kentucky) is switching from Central (-0600) to Eastern
+# (-0500) time. They won't "fall back" this year. See Sara Shipley,
+# The difference an hour makes, Nando Times (2000-08-29 15:33 -0400).
+#
+# From Paul Eggert (2001-07-16):
+# The final rule was published in the
+# <a href="http://frwebgate.access.gpo.gov/cgi-bin/getdoc.cgi?dbname=2000_register&docid=fr17au00-22">
+# Federal Register 65, 160 (2000-08-17), page 50154-50158.
+# </a>
+#
+Zone America/Kentucky/Monticello -5:39:24 - LMT 1883 Nov 18 12:20:36
+ -6:00 US C%sT 1946
+ -6:00 - CST 1968
+ -6:00 US C%sT 2000 Oct 29 2:00
+ -5:00 US E%sT
+
+
+# From Rives McDow (2000-08-30):
+# Here ... are all the changes in the US since 1985.
+# Kearny County, KS (put all of county on central;
+# previously split between MST and CST) ... 1990-10
+# Starke County, IN (from CST to EST) ... 1991-10
+# Oliver County, ND (from MST to CST) ... 1992-10
+# West Wendover, NV (from PST TO MST) ... 1999-10
+# Wayne County, KY (from CST to EST) ... 2000-10
+#
+# From Paul Eggert (2001-07-17):
+# We don't know where the line used to be within Kearny County, KS,
+# so omit that change for now.
+# See America/Indiana/Knox for the Starke County, IN change.
+# See America/North_Dakota/Center for the Oliver County, ND change.
+# West Wendover, NV officially switched from Pacific to mountain time on
+# 1999-10-31. See the
+# <a href="http://frwebgate.access.gpo.gov/cgi-bin/getdoc.cgi?dbname=1999_register&docid=fr21oc99-15">
+# Federal Register 64, 203 (1999-10-21), page 56705-56707.
+# </a>
+# However, the Federal Register says that West Wendover already operated
+# on mountain time, and the rule merely made this official;
+# hence a separate tz entry is not needed.
+
+# Michigan
+#
+# From Bob Devine (1988-01-28):
+# Michigan didn't observe DST from 1968 to 1973.
+#
+# From Paul Eggert (1999-03-31):
+# Shanks writes that Michigan started using standard time on 1885-09-18,
+# but Howse writes (pp 124-125, referring to Popular Astronomy, 1901-01)
+# that Detroit kept
+#
+# local time until 1900 when the City Council decreed that clocks should
+# be put back twenty-eight minutes to Central Standard Time. Half the
+# city obeyed, half refused. After considerable debate, the decision
+# was rescinded and the city reverted to Sun time. A derisive offer to
+# erect a sundial in front of the city hall was referred to the
+# Committee on Sewers. Then, in 1905, Central time was adopted
+# by city vote.
+#
+# This story is too entertaining to be false, so go with Howse over Shanks.
+#
+# From Paul Eggert (2001-03-06):
+# Garland (1927) writes ``Cleveland and Detroit advanced their clocks
+# one hour in 1914.'' This change is not in Shanks. We have no more
+# info, so omit this for now.
+#
+# Most of Michigan observed DST from 1973 on, but was a bit late in 1975.
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
+Rule Detroit 1948 only - Apr lastSun 2:00 1:00 D
+Rule Detroit 1948 only - Sep lastSun 2:00 0 S
+Rule Detroit 1967 only - Jun 14 2:00 1:00 D
+Rule Detroit 1967 only - Oct lastSun 2:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Detroit -5:32:11 - LMT 1905
+ -6:00 - CST 1915 May 15 2:00
+ -5:00 - EST 1942
+ -5:00 US E%sT 1946
+ -5:00 Detroit E%sT 1973
+ -5:00 US E%sT 1975
+ -5:00 - EST 1975 Apr 27 2:00
+ -5:00 US E%sT
+#
+# Dickinson, Gogebic, Iron, and Menominee Counties, Michigan,
+# switched from EST to CST/CDT in 1973.
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
+Rule Menominee 1946 only - Apr lastSun 2:00 1:00 D
+Rule Menominee 1946 only - Sep lastSun 2:00 0 S
+Rule Menominee 1966 only - Apr lastSun 2:00 1:00 D
+Rule Menominee 1966 only - Oct lastSun 2:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Menominee -5:50:27 - LMT 1885 Sep 18 12:00
+ -6:00 US C%sT 1946
+ -6:00 Menominee C%sT 1969 Apr 27 2:00
+ -5:00 - EST 1973 Apr 29 2:00
+ -6:00 US C%sT
+
+# Navassa
+# administered by the US Fish and Wildlife Service
+# claimed by US under the provisions of the 1856 Guano Islands Act
+# also claimed by Haiti
+# occupied 1857/1900 by the Navassa Phosphate Co
+# US lighthouse 1917/1996-09
+# currently uninhabited
+# see Mark Fineman, ``An Isle Rich in Guano and Discord'',
+# _Los Angeles Times_ (1998-11-10), A1, A10; it cites
+# Jimmy Skaggs, _The Great Guano Rush_ (1994).
+
+################################################################################
+
+
+# From Paul Eggert (2006-03-22):
+# A good source for time zone historical data outside the U.S. is
+# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
+# San Diego: ACS Publications, Inc. (2003).
+#
+# Gwillim Law writes that a good source
+# for recent time zone data is the International Air Transport
+# Association's Standard Schedules Information Manual (IATA SSIM),
+# published semiannually. Law sent in several helpful summaries
+# of the IATA's data after 1990.
+#
+# Except where otherwise noted, Shanks & Pottenger is the source for
+# entries through 1990, and IATA SSIM is the source for entries afterwards.
+#
+# Other sources occasionally used include:
+#
+# Edward W. Whitman, World Time Differences,
+# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated),
+# which I found in the UCLA library.
+#
+# <a href="http://www.pettswoodvillage.co.uk/Daylight_Savings_William_Willett.pdf">
+# William Willett, The Waste of Daylight, 19th edition
+# </a> (1914-03)
+#
+# See the `europe' file for Greenland.
+
+# Canada
+
+# From Alain LaBont<e'> (1994-11-14):
+# I post here the time zone abbreviations standardized in Canada
+# for both English and French in the CAN/CSA-Z234.4-89 standard....
+#
+# UTC Standard time Daylight savings time
+# offset French English French English
+# -2:30 - - HAT NDT
+# -3 - - HAA ADT
+# -3:30 HNT NST - -
+# -4 HNA AST HAE EDT
+# -5 HNE EST HAC CDT
+# -6 HNC CST HAR MDT
+# -7 HNR MST HAP PDT
+# -8 HNP PST HAY YDT
+# -9 HNY YST - -
+#
+# HN: Heure Normale ST: Standard Time
+# HA: Heure Avanc<e'>e DT: Daylight saving Time
+#
+# A: de l'Atlantique Atlantic
+# C: du Centre Central
+# E: de l'Est Eastern
+# M: Mountain
+# N: Newfoundland
+# P: du Pacifique Pacific
+# R: des Rocheuses
+# T: de Terre-Neuve
+# Y: du Yukon Yukon
+#
+# From Paul Eggert (1994-11-22):
+# Alas, this sort of thing must be handled by localization software.
+
+# Unless otherwise specified, the data for Canada are all from Shanks
+# & Pottenger.
+
+# From Chris Walton (2006-04-01, 2006-04-25, 2006-06-26, 2007-01-31,
+# 2007-03-01):
+# The British Columbia government announced yesterday that it will
+# adjust daylight savings next year to align with changes in the
+# U.S. and the rest of Canada....
+# http://www2.news.gov.bc.ca/news_releases_2005-2009/2006AG0014-000330.htm
+# ...
+# Nova Scotia
+# Daylight saving time will be extended by four weeks starting in 2007....
+# http://www.gov.ns.ca/just/regulations/rg2/2006/ma1206.pdf
+#
+# [For New Brunswick] the new legislation dictates that the time change is to
+# be done at 02:00 instead of 00:01.
+# http://www.gnb.ca/0062/acts/BBA-2006/Chap-19.pdf
+# ...
+# Manitoba has traditionally changed the clock every fall at 03:00.
+# As of 2006, the transition is to take place one hour earlier at 02:00.
+# http://web2.gov.mb.ca/laws/statutes/ccsm/o030e.php
+# ...
+# [Alberta, Ontario, Quebec] will follow US rules.
+# http://www.qp.gov.ab.ca/documents/spring/CH03_06.CFM
+# http://www.e-laws.gov.on.ca/DBLaws/Source/Regs/English/2006/R06111_e.htm
+# http://www2.publicationsduquebec.gouv.qc.ca/dynamicSearch/telecharge.php?type=5&file=2006C39A.PDF
+# ...
+# P.E.I. will follow US rules....
+# http://www.assembly.pe.ca/bills/pdf_chapter/62/3/chapter-41.pdf
+# ...
+# Province of Newfoundland and Labrador....
+# http://www.hoa.gov.nl.ca/hoa/bills/Bill0634.htm
+# ...
+# Yukon
+# http://www.gov.yk.ca/legislation/regs/oic2006_127.pdf
+# ...
+# N.W.T. will follow US rules. Whoever maintains the government web site
+# does not seem to believe in bookmarks. To see the news release, click the
+# following link and search for "Daylight Savings Time Change". Press the
+# "Daylight Savings Time Change" link; it will fire off a popup using
+# JavaScript.
+# http://www.exec.gov.nt.ca/currentnews/currentPR.asp?mode=archive
+# ...
+# Nunavut
+# An amendment to the Interpretation Act was registered on February 19/2007....
+# http://action.attavik.ca/home/justice-gn/attach/2007/gaz02part2.pdf
+
+# From Paul Eggert (2006-04-25):
+# H. David Matthews and Mary Vincent's map
+# <a href="http://www.canadiangeographic.ca/Magazine/SO98/geomap.asp">
+# "It's about TIME", _Canadian Geographic_ (September-October 1998)
+# </a> contains detailed boundaries for regions observing nonstandard
+# time and daylight saving time arrangements in Canada circa 1998.
+#
+# INMS, the Institute for National Measurement Standards in Ottawa, has <a
+# href="http://inms-ienm.nrc-cnrc.gc.ca/en/time_services/daylight_saving_e.php">
+# information about standard and daylight saving time zones in Canada.
+# </a> (updated periodically).
+# Its unofficial information is often taken from Matthews and Vincent.
+
+# From Paul Eggert (2006-06-27):
+# For now, assume all of DST-observing Canada will fall into line with the
+# new US DST rules,
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Canada 1918 only - Apr 14 2:00 1:00 D
+Rule Canada 1918 only - Oct 31 2:00 0 S
+Rule Canada 1942 only - Feb 9 2:00 1:00 W # War
+Rule Canada 1945 only - Aug 14 23:00u 1:00 P # Peace
+Rule Canada 1945 only - Sep 30 2:00 0 S
+Rule Canada 1974 1986 - Apr lastSun 2:00 1:00 D
+Rule Canada 1974 2006 - Oct lastSun 2:00 0 S
+Rule Canada 1987 2006 - Apr Sun>=1 2:00 1:00 D
+Rule Canada 2007 max - Mar Sun>=8 2:00 1:00 D
+Rule Canada 2007 max - Nov Sun>=1 2:00 0 S
+
+
+# Newfoundland and Labrador
+
+# From Paul Eggert (2000-10-02):
+# Matthews and Vincent (1998) write that Labrador should use NST/NDT,
+# but the only part of Labrador that follows the rules is the
+# southeast corner, including Port Hope Simpson and Mary's Harbour,
+# but excluding, say, Black Tickle.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule StJohns 1917 only - Apr 8 2:00 1:00 D
+Rule StJohns 1917 only - Sep 17 2:00 0 S
+# Whitman gives 1919 Apr 5 and 1920 Apr 5; go with Shanks & Pottenger.
+Rule StJohns 1919 only - May 5 23:00 1:00 D
+Rule StJohns 1919 only - Aug 12 23:00 0 S
+# For 1931-1935 Whitman gives Apr same date; go with Shanks & Pottenger.
+Rule StJohns 1920 1935 - May Sun>=1 23:00 1:00 D
+Rule StJohns 1920 1935 - Oct lastSun 23:00 0 S
+# For 1936-1941 Whitman gives May Sun>=8 and Oct Sun>=1; go with Shanks &
+# Pottenger.
+Rule StJohns 1936 1941 - May Mon>=9 0:00 1:00 D
+Rule StJohns 1936 1941 - Oct Mon>=2 0:00 0 S
+# Whitman gives the following transitions:
+# 1942 03-01/12-31, 1943 05-30/09-05, 1944 07-10/09-02, 1945 01-01/10-07
+# but go with Shanks & Pottenger and assume they used Canadian rules.
+# For 1946-9 Whitman gives May 5,4,9,1 - Oct 1,5,3,2, and for 1950 he gives
+# Apr 30 - Sep 24; go with Shanks & Pottenger.
+Rule StJohns 1946 1950 - May Sun>=8 2:00 1:00 D
+Rule StJohns 1946 1950 - Oct Sun>=2 2:00 0 S
+Rule StJohns 1951 1986 - Apr lastSun 2:00 1:00 D
+Rule StJohns 1951 1959 - Sep lastSun 2:00 0 S
+Rule StJohns 1960 1986 - Oct lastSun 2:00 0 S
+# From Paul Eggert (2000-10-02):
+# INMS (2000-09-12) says that, since 1988 at least, Newfoundland switches
+# at 00:01 local time. For now, assume it started in 1987.
+Rule StJohns 1987 only - Apr Sun>=1 0:01 1:00 D
+Rule StJohns 1987 2006 - Oct lastSun 0:01 0 S
+Rule StJohns 1988 only - Apr Sun>=1 0:01 2:00 DD
+Rule StJohns 1989 2006 - Apr Sun>=1 0:01 1:00 D
+Rule StJohns 2007 max - Mar Sun>=8 0:01 1:00 D
+Rule StJohns 2007 max - Nov Sun>=1 0:01 0 S
+#
+# St John's has an apostrophe, but Posix file names can't have apostrophes.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/St_Johns -3:30:52 - LMT 1884
+ -3:30:52 StJohns N%sT 1918
+ -3:30:52 Canada N%sT 1919
+ -3:30:52 StJohns N%sT 1935 Mar 30
+ -3:30 StJohns N%sT 1942 May 11
+ -3:30 Canada N%sT 1946
+ -3:30 StJohns N%sT
+
+# most of east Labrador
+
+# The name `Happy Valley-Goose Bay' is too long; use `Goose Bay'.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Goose_Bay -4:01:40 - LMT 1884 # Happy Valley-Goose Bay
+ -3:30:52 - NST 1918
+ -3:30:52 Canada N%sT 1919
+ -3:30:52 - NST 1935 Mar 30
+ -3:30 - NST 1936
+ -3:30 StJohns N%sT 1942 May 11
+ -3:30 Canada N%sT 1946
+ -3:30 StJohns N%sT 1966 Mar 15 2:00
+ -4:00 StJohns A%sT
+
+
+# west Labrador, Nova Scotia, Prince Edward I
+
+# From Paul Eggert (2006-03-22):
+# Shanks & Pottenger write that since 1970 most of this region has been like
+# Halifax. Many locales did not observe peacetime DST until 1972;
+# Glace Bay, NS is the largest that we know of.
+# Shanks & Pottenger also write that Liverpool, NS was the only town
+# in Canada to observe DST in 1971 but not 1970; for now we'll assume
+# this is a typo.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Halifax 1916 only - Apr 1 0:00 1:00 D
+Rule Halifax 1916 only - Oct 1 0:00 0 S
+Rule Halifax 1920 only - May 9 0:00 1:00 D
+Rule Halifax 1920 only - Aug 29 0:00 0 S
+Rule Halifax 1921 only - May 6 0:00 1:00 D
+Rule Halifax 1921 1922 - Sep 5 0:00 0 S
+Rule Halifax 1922 only - Apr 30 0:00 1:00 D
+Rule Halifax 1923 1925 - May Sun>=1 0:00 1:00 D
+Rule Halifax 1923 only - Sep 4 0:00 0 S
+Rule Halifax 1924 only - Sep 15 0:00 0 S
+Rule Halifax 1925 only - Sep 28 0:00 0 S
+Rule Halifax 1926 only - May 16 0:00 1:00 D
+Rule Halifax 1926 only - Sep 13 0:00 0 S
+Rule Halifax 1927 only - May 1 0:00 1:00 D
+Rule Halifax 1927 only - Sep 26 0:00 0 S
+Rule Halifax 1928 1931 - May Sun>=8 0:00 1:00 D
+Rule Halifax 1928 only - Sep 9 0:00 0 S
+Rule Halifax 1929 only - Sep 3 0:00 0 S
+Rule Halifax 1930 only - Sep 15 0:00 0 S
+Rule Halifax 1931 1932 - Sep Mon>=24 0:00 0 S
+Rule Halifax 1932 only - May 1 0:00 1:00 D
+Rule Halifax 1933 only - Apr 30 0:00 1:00 D
+Rule Halifax 1933 only - Oct 2 0:00 0 S
+Rule Halifax 1934 only - May 20 0:00 1:00 D
+Rule Halifax 1934 only - Sep 16 0:00 0 S
+Rule Halifax 1935 only - Jun 2 0:00 1:00 D
+Rule Halifax 1935 only - Sep 30 0:00 0 S
+Rule Halifax 1936 only - Jun 1 0:00 1:00 D
+Rule Halifax 1936 only - Sep 14 0:00 0 S
+Rule Halifax 1937 1938 - May Sun>=1 0:00 1:00 D
+Rule Halifax 1937 1941 - Sep Mon>=24 0:00 0 S
+Rule Halifax 1939 only - May 28 0:00 1:00 D
+Rule Halifax 1940 1941 - May Sun>=1 0:00 1:00 D
+Rule Halifax 1946 1949 - Apr lastSun 2:00 1:00 D
+Rule Halifax 1946 1949 - Sep lastSun 2:00 0 S
+Rule Halifax 1951 1954 - Apr lastSun 2:00 1:00 D
+Rule Halifax 1951 1954 - Sep lastSun 2:00 0 S
+Rule Halifax 1956 1959 - Apr lastSun 2:00 1:00 D
+Rule Halifax 1956 1959 - Sep lastSun 2:00 0 S
+Rule Halifax 1962 1973 - Apr lastSun 2:00 1:00 D
+Rule Halifax 1962 1973 - Oct lastSun 2:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Halifax -4:14:24 - LMT 1902 Jun 15
+ -4:00 Halifax A%sT 1918
+ -4:00 Canada A%sT 1919
+ -4:00 Halifax A%sT 1942 Feb 9 2:00s
+ -4:00 Canada A%sT 1946
+ -4:00 Halifax A%sT 1974
+ -4:00 Canada A%sT
+Zone America/Glace_Bay -3:59:48 - LMT 1902 Jun 15
+ -4:00 Canada A%sT 1953
+ -4:00 Halifax A%sT 1954
+ -4:00 - AST 1972
+ -4:00 Halifax A%sT 1974
+ -4:00 Canada A%sT
+
+# New Brunswick
+
+# From Paul Eggert (2007-01-31):
+# The Time Definition Act <http://www.gnb.ca/0062/PDF-acts/t-06.pdf>
+# says they changed at 00:01 through 2006, and
+# <http://www.canlii.org/nb/laws/sta/t-6/20030127/whole.html> makes it
+# clear that this was the case since at least 1993.
+# For now, assume it started in 1993.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Moncton 1933 1935 - Jun Sun>=8 1:00 1:00 D
+Rule Moncton 1933 1935 - Sep Sun>=8 1:00 0 S
+Rule Moncton 1936 1938 - Jun Sun>=1 1:00 1:00 D
+Rule Moncton 1936 1938 - Sep Sun>=1 1:00 0 S
+Rule Moncton 1939 only - May 27 1:00 1:00 D
+Rule Moncton 1939 1941 - Sep Sat>=21 1:00 0 S
+Rule Moncton 1940 only - May 19 1:00 1:00 D
+Rule Moncton 1941 only - May 4 1:00 1:00 D
+Rule Moncton 1946 1972 - Apr lastSun 2:00 1:00 D
+Rule Moncton 1946 1956 - Sep lastSun 2:00 0 S
+Rule Moncton 1957 1972 - Oct lastSun 2:00 0 S
+Rule Moncton 1993 2006 - Apr Sun>=1 0:01 1:00 D
+Rule Moncton 1993 2006 - Oct lastSun 0:01 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Moncton -4:19:08 - LMT 1883 Dec 9
+ -5:00 - EST 1902 Jun 15
+ -4:00 Canada A%sT 1933
+ -4:00 Moncton A%sT 1942
+ -4:00 Canada A%sT 1946
+ -4:00 Moncton A%sT 1973
+ -4:00 Canada A%sT 1993
+ -4:00 Moncton A%sT 2007
+ -4:00 Canada A%sT
+
+# Quebec
+
+# From Paul Eggert (2006-07-09):
+# Shanks & Pottenger write that since 1970 most of Quebec has been
+# like Montreal.
+
+# From Paul Eggert (2006-06-27):
+# Matthews and Vincent (1998) also write that Quebec east of the -63
+# meridian is supposed to observe AST, but residents as far east as
+# Natashquan use EST/EDT, and residents east of Natashquan use AST.
+# In "Official time in Quebec" the Quebec department of justice writes in
+# http://www.justice.gouv.qc.ca/english/publications/generale/temps-regl-1-a.htm
+# that "The residents of the Municipality of the
+# Cote-Nord-du-Golfe-Saint-Laurent and the municipalities of Saint-Augustin,
+# Bonne-Esperance and Blanc-Sablon apply the Official Time Act as it is
+# written and use Atlantic standard time all year round. The same applies to
+# the residents of the Native facilities along the lower North Shore."
+# <http://www.assnat.qc.ca/eng/37legislature2/Projets-loi/Publics/06-a002.htm>
+# says this common practice was codified into law as of 2007.
+# For lack of better info, guess this practice began around 1970, contra to
+# Shanks & Pottenger who have this region observing AST/ADT.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Mont 1917 only - Mar 25 2:00 1:00 D
+Rule Mont 1917 only - Apr 24 0:00 0 S
+Rule Mont 1919 only - Mar 31 2:30 1:00 D
+Rule Mont 1919 only - Oct 25 2:30 0 S
+Rule Mont 1920 only - May 2 2:30 1:00 D
+Rule Mont 1920 1922 - Oct Sun>=1 2:30 0 S
+Rule Mont 1921 only - May 1 2:00 1:00 D
+Rule Mont 1922 only - Apr 30 2:00 1:00 D
+Rule Mont 1924 only - May 17 2:00 1:00 D
+Rule Mont 1924 1926 - Sep lastSun 2:30 0 S
+Rule Mont 1925 1926 - May Sun>=1 2:00 1:00 D
+# The 1927-to-1937 rules can be expressed more simply as
+# Rule Mont 1927 1937 - Apr lastSat 24:00 1:00 D
+# Rule Mont 1927 1937 - Sep lastSat 24:00 0 S
+# The rules below avoid use of 24:00
+# (which pre-1998 versions of zic cannot handle).
+Rule Mont 1927 only - May 1 0:00 1:00 D
+Rule Mont 1927 1932 - Sep lastSun 0:00 0 S
+Rule Mont 1928 1931 - Apr lastSun 0:00 1:00 D
+Rule Mont 1932 only - May 1 0:00 1:00 D
+Rule Mont 1933 1940 - Apr lastSun 0:00 1:00 D
+Rule Mont 1933 only - Oct 1 0:00 0 S
+Rule Mont 1934 1939 - Sep lastSun 0:00 0 S
+Rule Mont 1946 1973 - Apr lastSun 2:00 1:00 D
+Rule Mont 1945 1948 - Sep lastSun 2:00 0 S
+Rule Mont 1949 1950 - Oct lastSun 2:00 0 S
+Rule Mont 1951 1956 - Sep lastSun 2:00 0 S
+Rule Mont 1957 1973 - Oct lastSun 2:00 0 S
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Blanc-Sablon -3:48:28 - LMT 1884
+ -4:00 Canada A%sT 1970
+ -4:00 - AST
+Zone America/Montreal -4:54:16 - LMT 1884
+ -5:00 Mont E%sT 1918
+ -5:00 Canada E%sT 1919
+ -5:00 Mont E%sT 1942 Feb 9 2:00s
+ -5:00 Canada E%sT 1946
+ -5:00 Mont E%sT 1974
+ -5:00 Canada E%sT
+
+
+# Ontario
+
+# From Paul Eggert (2006-07-09):
+# Shanks & Pottenger write that since 1970 most of Ontario has been like
+# Toronto.
+# Thunder Bay skipped DST in 1973.
+# Many smaller locales did not observe peacetime DST until 1974;
+# Nipigon (EST) and Rainy River (CST) are the largest that we know of.
+# Far west Ontario is like Winnipeg; far east Quebec is like Halifax.
+
+# From Mark Brader (2003-07-26):
+# [According to the Toronto Star] Orillia, Ontario, adopted DST
+# effective Saturday, 1912-06-22, 22:00; the article mentions that
+# Port Arthur (now part of Thunder Bay, Ontario) as well as Moose Jaw
+# have already done so. In Orillia DST was to run until Saturday,
+# 1912-08-31 (no time mentioned), but it was met with considerable
+# hostility from certain segments of the public, and was revoked after
+# only two weeks -- I copied it as Saturday, 1912-07-07, 22:00, but
+# presumably that should be -07-06. (1912-06-19, -07-12; also letters
+# earlier in June).
+#
+# Kenora, Ontario, was to abandon DST on 1914-06-01 (-05-21).
+
+# From Paul Eggert (1997-10-17):
+# Mark Brader writes that an article in the 1997-10-14 Toronto Star
+# says that Atikokan, Ontario currently does not observe DST,
+# but will vote on 11-10 whether to use EST/EDT.
+# He also writes that the
+# <a href="http://www.gov.on.ca/MBS/english/publications/statregs/conttext.html">
+# Ontario Time Act (1990, Chapter T.9)
+# </a>
+# says that Ontario east of 90W uses EST/EDT, and west of 90W uses CST/CDT.
+# Officially Atikokan is therefore on CST/CDT, and most likely this report
+# concerns a non-official time observed as a matter of local practice.
+#
+# From Paul Eggert (2000-10-02):
+# Matthews and Vincent (1998) write that Atikokan, Pickle Lake, and
+# New Osnaburgh observe CST all year, that Big Trout Lake observes
+# CST/CDT, and that Upsala and Shebandowan observe EST/EDT, all in
+# violation of the official Ontario rules.
+#
+# From Paul Eggert (2006-07-09):
+# Chris Walton (2006-07-06) mentioned an article by Stephanie MacLellan in the
+# 2005-07-21 Chronicle-Journal, which said:
+#
+# The clocks in Atikokan stay set on standard time year-round.
+# This means they spend about half the time on central time and
+# the other half on eastern time.
+#
+# For the most part, the system works, Mayor Dennis Brown said.
+#
+# "The majority of businesses in Atikokan deal more with Eastern
+# Canada, but there are some that deal with Western Canada," he
+# said. "I don't see any changes happening here."
+#
+# Walton also writes "Supposedly Pickle Lake and Mishkeegogamang
+# [New Osnaburgh] follow the same practice."
+
+# From Garry McKinnon (2006-07-14) via Chris Walton:
+# I chatted with a member of my board who has an outstanding memory
+# and a long history in Atikokan (and in the telecom industry) and he
+# can say for certain that Atikokan has been practicing the current
+# time keeping since 1952, at least.
+
+# From Paul Eggert (2006-07-17):
+# Shanks & Pottenger say that Atikokan has agreed with Rainy River
+# ever since standard time was introduced, but the information from
+# McKinnon sounds more authoritative. For now, assume that Atikokan
+# switched to EST immediately after WWII era daylight saving time
+# ended. This matches the old (less-populous) America/Coral_Harbour
+# entry since our cutoff date of 1970, so we can move
+# America/Coral_Harbour to the 'backward' file.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Toronto 1919 only - Mar 30 23:30 1:00 D
+Rule Toronto 1919 only - Oct 26 0:00 0 S
+Rule Toronto 1920 only - May 2 2:00 1:00 D
+Rule Toronto 1920 only - Sep 26 0:00 0 S
+Rule Toronto 1921 only - May 15 2:00 1:00 D
+Rule Toronto 1921 only - Sep 15 2:00 0 S
+Rule Toronto 1922 1923 - May Sun>=8 2:00 1:00 D
+# Shanks & Pottenger say 1923-09-19; assume it's a typo and that "-16"
+# was meant.
+Rule Toronto 1922 1926 - Sep Sun>=15 2:00 0 S
+Rule Toronto 1924 1927 - May Sun>=1 2:00 1:00 D
+# The 1927-to-1939 rules can be expressed more simply as
+# Rule Toronto 1927 1937 - Sep Sun>=25 2:00 0 S
+# Rule Toronto 1928 1937 - Apr Sun>=25 2:00 1:00 D
+# Rule Toronto 1938 1940 - Apr lastSun 2:00 1:00 D
+# Rule Toronto 1938 1939 - Sep lastSun 2:00 0 S
+# The rules below avoid use of Sun>=25
+# (which pre-2004 versions of zic cannot handle).
+Rule Toronto 1927 1932 - Sep lastSun 2:00 0 S
+Rule Toronto 1928 1931 - Apr lastSun 2:00 1:00 D
+Rule Toronto 1932 only - May 1 2:00 1:00 D
+Rule Toronto 1933 1940 - Apr lastSun 2:00 1:00 D
+Rule Toronto 1933 only - Oct 1 2:00 0 S
+Rule Toronto 1934 1939 - Sep lastSun 2:00 0 S
+Rule Toronto 1945 1946 - Sep lastSun 2:00 0 S
+Rule Toronto 1946 only - Apr lastSun 2:00 1:00 D
+Rule Toronto 1947 1949 - Apr lastSun 0:00 1:00 D
+Rule Toronto 1947 1948 - Sep lastSun 0:00 0 S
+Rule Toronto 1949 only - Nov lastSun 0:00 0 S
+Rule Toronto 1950 1973 - Apr lastSun 2:00 1:00 D
+Rule Toronto 1950 only - Nov lastSun 2:00 0 S
+Rule Toronto 1951 1956 - Sep lastSun 2:00 0 S
+# Shanks & Pottenger say Toronto ended DST a week early in 1971,
+# namely on 1971-10-24, but Mark Brader wrote (2003-05-31) that this
+# is wrong, and that he had confirmed it by checking the 1971-10-30
+# Toronto Star, which said that DST was ending 1971-10-31 as usual.
+Rule Toronto 1957 1973 - Oct lastSun 2:00 0 S
+
+# From Paul Eggert (2003-07-27):
+# Willett (1914-03) writes (p. 17) "In the Cities of Fort William, and
+# Port Arthur, Ontario, the principle of the Bill has been in
+# operation for the past three years, and in the City of Moose Jaw,
+# Saskatchewan, for one year."
+
+# From David Bryan via Tory Tronrud, Director/Curator,
+# Thunder Bay Museum (2003-11-12):
+# There is some suggestion, however, that, by-law or not, daylight
+# savings time was being practiced in Fort William and Port Arthur
+# before 1909.... [I]n 1910, the line between the Eastern and Central
+# Time Zones was permanently moved about two hundred miles west to
+# include the Thunder Bay area.... When Canada adopted daylight
+# savings time in 1916, Fort William and Port Arthur, having done so
+# already, did not change their clocks.... During the Second World
+# War,... [t]he cities agreed to implement DST during the summer
+# months for the remainder of the war years.
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Toronto -5:17:32 - LMT 1895
+ -5:00 Canada E%sT 1919
+ -5:00 Toronto E%sT 1942 Feb 9 2:00s
+ -5:00 Canada E%sT 1946
+ -5:00 Toronto E%sT 1974
+ -5:00 Canada E%sT
+Zone America/Thunder_Bay -5:57:00 - LMT 1895
+ -6:00 - CST 1910
+ -5:00 - EST 1942
+ -5:00 Canada E%sT 1970
+ -5:00 Mont E%sT 1973
+ -5:00 - EST 1974
+ -5:00 Canada E%sT
+Zone America/Nipigon -5:53:04 - LMT 1895
+ -5:00 Canada E%sT 1940 Sep 29
+ -5:00 1:00 EDT 1942 Feb 9 2:00s
+ -5:00 Canada E%sT
+Zone America/Rainy_River -6:18:16 - LMT 1895
+ -6:00 Canada C%sT 1940 Sep 29
+ -6:00 1:00 CDT 1942 Feb 9 2:00s
+ -6:00 Canada C%sT
+Zone America/Atikokan -6:06:28 - LMT 1895
+ -6:00 Canada C%sT 1940 Sep 29
+ -6:00 1:00 CDT 1942 Feb 9 2:00s
+ -6:00 Canada C%sT 1945 Sep 30 2:00
+ -5:00 - EST
+
+
+# Manitoba
+
+# From Rob Douglas (2006-04-06):
+# the old Manitoba Time Act - as amended by Bill 2, assented to
+# March 27, 1987 ... said ...
+# "between two o'clock Central Standard Time in the morning of
+# the first Sunday of April of each year and two o'clock Central
+# Standard Time in the morning of the last Sunday of October next
+# following, one hour in advance of Central Standard Time."...
+# I believe that the English legislation [of the old time act] had =
+# been assented to (March 22, 1967)....
+# Also, as far as I can tell, there was no order-in-council varying
+# the time of Daylight Saving Time for 2005 and so the provisions of
+# the 1987 version would apply - the changeover was at 2:00 Central
+# Standard Time (i.e. not until 3:00 Central Daylight Time).
+
+# From Paul Eggert (2006-04-10):
+# Shanks & Pottenger say Manitoba switched at 02:00 (not 02:00s)
+# starting 1966. Since 02:00s is clearly correct for 1967 on, assume
+# it was also 02:00s in 1966.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Winn 1916 only - Apr 23 0:00 1:00 D
+Rule Winn 1916 only - Sep 17 0:00 0 S
+Rule Winn 1918 only - Apr 14 2:00 1:00 D
+Rule Winn 1918 only - Oct 31 2:00 0 S
+Rule Winn 1937 only - May 16 2:00 1:00 D
+Rule Winn 1937 only - Sep 26 2:00 0 S
+Rule Winn 1942 only - Feb 9 2:00 1:00 W # War
+Rule Winn 1945 only - Aug 14 23:00u 1:00 P # Peace
+Rule Winn 1945 only - Sep lastSun 2:00 0 S
+Rule Winn 1946 only - May 12 2:00 1:00 D
+Rule Winn 1946 only - Oct 13 2:00 0 S
+Rule Winn 1947 1949 - Apr lastSun 2:00 1:00 D
+Rule Winn 1947 1949 - Sep lastSun 2:00 0 S
+Rule Winn 1950 only - May 1 2:00 1:00 D
+Rule Winn 1950 only - Sep 30 2:00 0 S
+Rule Winn 1951 1960 - Apr lastSun 2:00 1:00 D
+Rule Winn 1951 1958 - Sep lastSun 2:00 0 S
+Rule Winn 1959 only - Oct lastSun 2:00 0 S
+Rule Winn 1960 only - Sep lastSun 2:00 0 S
+Rule Winn 1963 only - Apr lastSun 2:00 1:00 D
+Rule Winn 1963 only - Sep 22 2:00 0 S
+Rule Winn 1966 1986 - Apr lastSun 2:00s 1:00 D
+Rule Winn 1966 2005 - Oct lastSun 2:00s 0 S
+Rule Winn 1987 2005 - Apr Sun>=1 2:00s 1:00 D
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Winnipeg -6:28:36 - LMT 1887 Jul 16
+ -6:00 Winn C%sT 2006
+ -6:00 Canada C%sT
+
+
+# Saskatchewan
+
+# From Mark Brader (2003-07-26):
+# The first actual adoption of DST in Canada was at the municipal
+# level. As the [Toronto] Star put it (1912-06-07), "While people
+# elsewhere have long been talking of legislation to save daylight,
+# the city of Moose Jaw [Saskatchewan] has acted on its own hook."
+# DST in Moose Jaw began on Saturday, 1912-06-01 (no time mentioned:
+# presumably late evening, as below), and would run until "the end of
+# the summer". The discrepancy between municipal time and railroad
+# time was noted.
+
+# From Paul Eggert (2003-07-27):
+# Willett (1914-03) notes that DST "has been in operation ... in the
+# City of Moose Jaw, Saskatchewan, for one year."
+
+# From Paul Eggert (2006-03-22):
+# Shanks & Pottenger say that since 1970 this region has mostly been as Regina.
+# Some western towns (e.g. Swift Current) switched from MST/MDT to CST in 1972.
+# Other western towns (e.g. Lloydminster) are like Edmonton.
+# Matthews and Vincent (1998) write that Denare Beach and Creighton
+# are like Winnipeg, in violation of Saskatchewan law.
+
+# From W. Jones (1992-11-06):
+# The. . .below is based on information I got from our law library, the
+# provincial archives, and the provincial Community Services department.
+# A precise history would require digging through newspaper archives, and
+# since you didn't say what you wanted, I didn't bother.
+#
+# Saskatchewan is split by a time zone meridian (105W) and over the years
+# the boundary became pretty ragged as communities near it reevaluated
+# their affiliations in one direction or the other. In 1965 a provincial
+# referendum favoured legislating common time practices.
+#
+# On 15 April 1966 the Time Act (c. T-14, Revised Statutes of
+# Saskatchewan 1978) was proclaimed, and established that the eastern
+# part of Saskatchewan would use CST year round, that districts in
+# northwest Saskatchewan would by default follow CST but could opt to
+# follow Mountain Time rules (thus 1 hour difference in the winter and
+# zero in the summer), and that districts in southwest Saskatchewan would
+# by default follow MT but could opt to follow CST.
+#
+# It took a few years for the dust to settle (I know one story of a town
+# on one time zone having its school in another, such that a mom had to
+# serve her family lunch in two shifts), but presently it seems that only
+# a few towns on the border with Alberta (e.g. Lloydminster) follow MT
+# rules any more; all other districts appear to have used CST year round
+# since sometime in the 1960s.
+
+# From Chris Walton (2006-06-26):
+# The Saskatchewan time act which was last updated in 1996 is about 30 pages
+# long and rather painful to read.
+# http://www.qp.gov.sk.ca/documents/English/Statutes/Statutes/T14.pdf
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Regina 1918 only - Apr 14 2:00 1:00 D
+Rule Regina 1918 only - Oct 31 2:00 0 S
+Rule Regina 1930 1934 - May Sun>=1 0:00 1:00 D
+Rule Regina 1930 1934 - Oct Sun>=1 0:00 0 S
+Rule Regina 1937 1941 - Apr Sun>=8 0:00 1:00 D
+Rule Regina 1937 only - Oct Sun>=8 0:00 0 S
+Rule Regina 1938 only - Oct Sun>=1 0:00 0 S
+Rule Regina 1939 1941 - Oct Sun>=8 0:00 0 S
+Rule Regina 1942 only - Feb 9 2:00 1:00 W # War
+Rule Regina 1945 only - Aug 14 23:00u 1:00 P # Peace
+Rule Regina 1945 only - Sep lastSun 2:00 0 S
+Rule Regina 1946 only - Apr Sun>=8 2:00 1:00 D
+Rule Regina 1946 only - Oct Sun>=8 2:00 0 S
+Rule Regina 1947 1957 - Apr lastSun 2:00 1:00 D
+Rule Regina 1947 1957 - Sep lastSun 2:00 0 S
+Rule Regina 1959 only - Apr lastSun 2:00 1:00 D
+Rule Regina 1959 only - Oct lastSun 2:00 0 S
+#
+Rule Swift 1957 only - Apr lastSun 2:00 1:00 D
+Rule Swift 1957 only - Oct lastSun 2:00 0 S
+Rule Swift 1959 1961 - Apr lastSun 2:00 1:00 D
+Rule Swift 1959 only - Oct lastSun 2:00 0 S
+Rule Swift 1960 1961 - Sep lastSun 2:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Regina -6:58:36 - LMT 1905 Sep
+ -7:00 Regina M%sT 1960 Apr lastSun 2:00
+ -6:00 - CST
+Zone America/Swift_Current -7:11:20 - LMT 1905 Sep
+ -7:00 Canada M%sT 1946 Apr lastSun 2:00
+ -7:00 Regina M%sT 1950
+ -7:00 Swift M%sT 1972 Apr lastSun 2:00
+ -6:00 - CST
+
+
+# Alberta
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Edm 1918 1919 - Apr Sun>=8 2:00 1:00 D
+Rule Edm 1918 only - Oct 31 2:00 0 S
+Rule Edm 1919 only - May 27 2:00 0 S
+Rule Edm 1920 1923 - Apr lastSun 2:00 1:00 D
+Rule Edm 1920 only - Oct lastSun 2:00 0 S
+Rule Edm 1921 1923 - Sep lastSun 2:00 0 S
+Rule Edm 1942 only - Feb 9 2:00 1:00 W # War
+Rule Edm 1945 only - Aug 14 23:00u 1:00 P # Peace
+Rule Edm 1945 only - Sep lastSun 2:00 0 S
+Rule Edm 1947 only - Apr lastSun 2:00 1:00 D
+Rule Edm 1947 only - Sep lastSun 2:00 0 S
+Rule Edm 1967 only - Apr lastSun 2:00 1:00 D
+Rule Edm 1967 only - Oct lastSun 2:00 0 S
+Rule Edm 1969 only - Apr lastSun 2:00 1:00 D
+Rule Edm 1969 only - Oct lastSun 2:00 0 S
+Rule Edm 1972 1986 - Apr lastSun 2:00 1:00 D
+Rule Edm 1972 2006 - Oct lastSun 2:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Edmonton -7:33:52 - LMT 1906 Sep
+ -7:00 Edm M%sT 1987
+ -7:00 Canada M%sT
+
+
+# British Columbia
+
+# From Paul Eggert (2006-03-22):
+# Shanks & Pottenger write that since 1970 most of this region has
+# been like Vancouver.
+# Dawson Creek uses MST. Much of east BC is like Edmonton.
+# Matthews and Vincent (1998) write that Creston is like Dawson Creek.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Vanc 1918 only - Apr 14 2:00 1:00 D
+Rule Vanc 1918 only - Oct 31 2:00 0 S
+Rule Vanc 1942 only - Feb 9 2:00 1:00 W # War
+Rule Vanc 1945 only - Aug 14 23:00u 1:00 P # Peace
+Rule Vanc 1945 only - Sep 30 2:00 0 S
+Rule Vanc 1946 1986 - Apr lastSun 2:00 1:00 D
+Rule Vanc 1946 only - Oct 13 2:00 0 S
+Rule Vanc 1947 1961 - Sep lastSun 2:00 0 S
+Rule Vanc 1962 2006 - Oct lastSun 2:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Vancouver -8:12:28 - LMT 1884
+ -8:00 Vanc P%sT 1987
+ -8:00 Canada P%sT
+Zone America/Dawson_Creek -8:00:56 - LMT 1884
+ -8:00 Canada P%sT 1947
+ -8:00 Vanc P%sT 1972 Aug 30 2:00
+ -7:00 - MST
+
+
+# Northwest Territories, Nunavut, Yukon
+
+# From Paul Eggert (2006-03-22):
+# Dawson switched to PST in 1973. Inuvik switched to MST in 1979.
+# Mathew Englander (1996-10-07) gives the following refs:
+# * 1967. Paragraph 28(34)(g) of the Interpretation Act, S.C. 1967-68,
+# c. 7 defines Yukon standard time as UTC-9. This is still valid;
+# see Interpretation Act, R.S.C. 1985, c. I-21, s. 35(1).
+# * C.O. 1973/214 switched Yukon to PST on 1973-10-28 00:00.
+# * O.I.C. 1980/02 established DST.
+# * O.I.C. 1987/056 changed DST to Apr firstSun 2:00 to Oct lastSun 2:00.
+# Shanks & Pottenger say Yukon's 1973-10-28 switch was at 2:00; go
+# with Englander.
+# From Chris Walton (2006-06-26):
+# Here is a link to the old daylight saving portion of the interpretation
+# act which was last updated in 1987:
+# http://www.gov.yk.ca/legislation/regs/oic1987_056.pdf
+
+# From Rives McDow (1999-09-04):
+# Nunavut ... moved ... to incorporate the whole territory into one time zone.
+# <a href="http://www.nunatsiaq.com/nunavut/nvt90903_13.html">
+# Nunavut moves to single time zone Oct. 31
+# </a>
+#
+# From Antoine Leca (1999-09-06):
+# We then need to create a new timezone for the Kitikmeot region of Nunavut
+# to differentiate it from the Yellowknife region.
+
+# From Paul Eggert (1999-09-20):
+# <a href="http://www.nunavut.com/basicfacts/english/basicfacts_1territory.html">
+# Basic Facts: The New Territory
+# </a> (1999) reports that Pangnirtung operates on eastern time,
+# and that Coral Harbour does not observe DST. We don't know when
+# Pangnirtung switched to eastern time; we'll guess 1995.
+
+# From Rives McDow (1999-11-08):
+# On October 31, when the rest of Nunavut went to Central time,
+# Pangnirtung wobbled. Here is the result of their wobble:
+#
+# The following businesses and organizations in Pangnirtung use Central Time:
+#
+# First Air, Power Corp, Nunavut Construction, Health Center, RCMP,
+# Eastern Arctic National Parks, A & D Specialist
+#
+# The following businesses and organizations in Pangnirtung use Eastern Time:
+#
+# Hamlet office, All other businesses, Both schools, Airport operator
+#
+# This has made for an interesting situation there, which warranted the news.
+# No one there that I spoke with seems concerned, or has plans to
+# change the local methods of keeping time, as it evidently does not
+# really interfere with any activities or make things difficult locally.
+# They plan to celebrate New Year's turn-over twice, one hour apart,
+# so it appears that the situation will last at least that long.
+# The Nunavut Intergovernmental Affairs hopes that they will "come to
+# their senses", but the locals evidently don't see any problem with
+# the current state of affairs.
+
+# From Michaela Rodrigue, writing in the
+# <a href="http://www.nunatsiaq.com/archives/nunavut991130/nvt91119_17.html">
+# Nunatsiaq News (1999-11-19)</a>:
+# Clyde River, Pangnirtung and Sanikiluaq now operate with two time zones,
+# central - or Nunavut time - for government offices, and eastern time
+# for municipal offices and schools.... Igloolik [was similar but then]
+# made the switch to central time on Saturday, Nov. 6.
+
+# From Paul Eggert (2000-10-02):
+# Matthews and Vincent (1998) say the following, but we lack histories
+# for these potential new Zones.
+#
+# The Canadian Forces station at Alert uses Eastern Time while the
+# handful of residents at the Eureka weather station [in the Central
+# zone] skip daylight savings. Baffin Island, which is crossed by the
+# Central, Eastern and Atlantic Time zones only uses Eastern Time.
+# Gjoa Haven, Taloyoak and Pelly Bay all use Mountain instead of
+# Central Time and Southampton Island [in the Central zone] is not
+# required to use daylight savings.
+
+# From
+# <a href="http://www.nunatsiaq.com/archives/nunavut001130/nvt21110_02.html">
+# Nunavut now has two time zones
+# </a> (2000-11-10):
+# The Nunavut government would allow its employees in Kugluktuk and
+# Cambridge Bay to operate on central time year-round, putting them
+# one hour behind the rest of Nunavut for six months during the winter.
+# At the end of October the two communities had rebelled against
+# Nunavut's unified time zone, refusing to shift to eastern time with
+# the rest of the territory for the winter. Cambridge Bay remained on
+# central time, while Kugluktuk, even farther west, reverted to
+# mountain time, which they had used before the advent of Nunavut's
+# unified time zone in 1999.
+#
+# From Rives McDow (2001-01-20), quoting the Nunavut government:
+# The preceding decision came into effect at midnight, Saturday Nov 4, 2000.
+
+# From Paul Eggert (2000-12-04):
+# Let's just keep track of the official times for now.
+
+# From Rives McDow (2001-03-07):
+# The premier of Nunavut has issued a ministerial statement advising
+# that effective 2001-04-01, the territory of Nunavut will revert
+# back to three time zones (mountain, central, and eastern). Of the
+# cities in Nunavut, Coral Harbor is the only one that I know of that
+# has said it will not observe dst, staying on EST year round. I'm
+# checking for more info, and will get back to you if I come up with
+# more.
+# [Also see <http://www.nunatsiaq.com/nunavut/nvt10309_06.html> (2001-03-09).]
+
+# From Gwillim Law (2005-05-21):
+# According to maps at
+# http://inms-ienm.nrc-cnrc.gc.ca/images/time_services/TZ01SWE.jpg
+# http://inms-ienm.nrc-cnrc.gc.ca/images/time_services/TZ01SSE.jpg
+# (both dated 2003), and
+# http://www.canadiangeographic.ca/Magazine/SO98/geomap.asp
+# (from a 1998 Canadian Geographic article), the de facto and de jure time
+# for Southampton Island (at the north end of Hudson Bay) is UTC-5 all year
+# round. Using Google, it's easy to find other websites that confirm this.
+# I wasn't able to find how far back this time regimen goes, but since it
+# predates the creation of Nunavut, it probably goes back many years....
+# The Inuktitut name of Coral Harbour is Sallit, but it's rarely used.
+#
+# From Paul Eggert (2005-07-26):
+# For lack of better information, assume that Southampton Island observed
+# daylight saving only during wartime.
+
+# From Chris Walton (2007-03-01):
+# ... the community of Resolute (located on Cornwallis Island in
+# Nunavut) moved from Central Time to Eastern Time last November.
+# Basically the community did not change its clocks at the end of
+# daylight saving....
+# http://www.nnsl.com/frames/newspapers/2006-11/nov13_06none.html
+
+# From Chris Walton (2007-03-14):
+# Today I phoned the "hamlet office" to find out what Resolute was doing with
+# its clocks.
+#
+# The individual that answered the phone confirmed that the clocks did not
+# move at the end of daylight saving on October 29/2006. He also told me that
+# the clocks did not move this past weekend (March 11/2007)....
+#
+# America/Resolute should use the "Canada" Rule up to October 29/2006.
+# After that it should be fixed on Eastern Standard Time until further notice.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule NT_YK 1918 only - Apr 14 2:00 1:00 D
+Rule NT_YK 1918 only - Oct 27 2:00 0 S
+Rule NT_YK 1919 only - May 25 2:00 1:00 D
+Rule NT_YK 1919 only - Nov 1 0:00 0 S
+Rule NT_YK 1942 only - Feb 9 2:00 1:00 W # War
+Rule NT_YK 1945 only - Aug 14 23:00u 1:00 P # Peace
+Rule NT_YK 1945 only - Sep 30 2:00 0 S
+Rule NT_YK 1965 only - Apr lastSun 0:00 2:00 DD
+Rule NT_YK 1965 only - Oct lastSun 2:00 0 S
+Rule NT_YK 1980 1986 - Apr lastSun 2:00 1:00 D
+Rule NT_YK 1980 2006 - Oct lastSun 2:00 0 S
+Rule NT_YK 1987 2006 - Apr Sun>=1 2:00 1:00 D
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# aka Panniqtuuq
+Zone America/Pangnirtung 0 - zzz 1921 # trading post est.
+ -4:00 NT_YK A%sT 1995 Apr Sun>=1 2:00
+ -5:00 Canada E%sT 1999 Oct 31 2:00
+ -6:00 Canada C%sT 2000 Oct 29 2:00
+ -5:00 Canada E%sT
+# formerly Frobisher Bay
+Zone America/Iqaluit 0 - zzz 1942 Aug # Frobisher Bay est.
+ -5:00 NT_YK E%sT 1999 Oct 31 2:00
+ -6:00 Canada C%sT 2000 Oct 29 2:00
+ -5:00 Canada E%sT
+# aka Qausuittuq
+Zone America/Resolute 0 - zzz 1947 Aug 31 # Resolute founded
+ -6:00 NT_YK C%sT 2000 Oct 29 2:00
+ -5:00 - EST 2001 Apr 1 3:00
+ -6:00 Canada C%sT 2006 Oct 29 2:00
+ -5:00 - EST
+# aka Kangiqiniq
+Zone America/Rankin_Inlet 0 - zzz 1957 # Rankin Inlet founded
+ -6:00 NT_YK C%sT 2000 Oct 29 2:00
+ -5:00 - EST 2001 Apr 1 3:00
+ -6:00 Canada C%sT
+# aka Iqaluktuuttiaq
+Zone America/Cambridge_Bay 0 - zzz 1920 # trading post est.?
+ -7:00 NT_YK M%sT 1999 Oct 31 2:00
+ -6:00 Canada C%sT 2000 Oct 29 2:00
+ -5:00 - EST 2000 Nov 5 0:00
+ -6:00 - CST 2001 Apr 1 3:00
+ -7:00 Canada M%sT
+Zone America/Yellowknife 0 - zzz 1935 # Yellowknife founded?
+ -7:00 NT_YK M%sT 1980
+ -7:00 Canada M%sT
+Zone America/Inuvik 0 - zzz 1953 # Inuvik founded
+ -8:00 NT_YK P%sT 1979 Apr lastSun 2:00
+ -7:00 NT_YK M%sT 1980
+ -7:00 Canada M%sT
+Zone America/Whitehorse -9:00:12 - LMT 1900 Aug 20
+ -9:00 NT_YK Y%sT 1966 Jul 1 2:00
+ -8:00 NT_YK P%sT 1980
+ -8:00 Canada P%sT
+Zone America/Dawson -9:17:40 - LMT 1900 Aug 20
+ -9:00 NT_YK Y%sT 1973 Oct 28 0:00
+ -8:00 NT_YK P%sT 1980
+ -8:00 Canada P%sT
+
+
+###############################################################################
+
+# Mexico
+
+# From Paul Eggert (2001-03-05):
+# The Investigation and Analysis Service of the
+# Mexican Library of Congress (MLoC) has published a
+# <a href="http://www.cddhcu.gob.mx/bibliot/publica/inveyana/polisoc/horver/">
+# history of Mexican local time (in Spanish)
+# </a>.
+#
+# Here are the discrepancies between Shanks & Pottenger (S&P) and the MLoC.
+# (In all cases we go with the MLoC.)
+# S&P report that Baja was at -8:00 in 1922/1923.
+# S&P say the 1930 transition in Baja was 1930-11-16.
+# S&P report no DST during summer 1931.
+# S&P report a transition at 1932-03-30 23:00, not 1932-04-01.
+
+# From Gwillim Law (2001-02-20):
+# There are some other discrepancies between the Decrees page and the
+# tz database. I think they can best be explained by supposing that
+# the researchers who prepared the Decrees page failed to find some of
+# the relevant documents.
+
+# From Alan Perry (1996-02-15):
+# A guy from our Mexico subsidiary finally found the Presidential Decree
+# outlining the timezone changes in Mexico.
+#
+# ------------- Begin Forwarded Message -------------
+#
+# I finally got my hands on the Official Presidential Decree that sets up the
+# rules for the DST changes. The rules are:
+#
+# 1. The country is divided in 3 timezones:
+# - Baja California Norte (the Mexico/BajaNorte TZ)
+# - Baja California Sur, Nayarit, Sinaloa and Sonora (the Mexico/BajaSur TZ)
+# - The rest of the country (the Mexico/General TZ)
+#
+# 2. From the first Sunday in April at 2:00 AM to the last Sunday in October
+# at 2:00 AM, the times in each zone are as follows:
+# BajaNorte: GMT+7
+# BajaSur: GMT+6
+# General: GMT+5
+#
+# 3. The rest of the year, the times are as follows:
+# BajaNorte: GMT+8
+# BajaSur: GMT+7
+# General: GMT+6
+#
+# The Decree was published in Mexico's Official Newspaper on January 4th.
+#
+# -------------- End Forwarded Message --------------
+# From Paul Eggert (1996-06-12):
+# For an English translation of the decree, see
+# <a href="http://mexico-travel.com/extra/timezone_eng.html">
+# ``Diario Oficial: Time Zone Changeover'' (1996-01-04).
+# </a>
+
+# From Rives McDow (1998-10-08):
+# The State of Quintana Roo has reverted back to central STD and DST times
+# (i.e. UTC -0600 and -0500 as of 1998-08-02).
+
+# From Rives McDow (2000-01-10):
+# Effective April 4, 1999 at 2:00 AM local time, Sonora changed to the time
+# zone 5 hours from the International Date Line, and will not observe daylight
+# savings time so as to stay on the same time zone as the southern part of
+# Arizona year round.
+
+# From Jesper Norgaard, translating
+# <http://www.reforma.com/nacional/articulo/064327/> (2001-01-17):
+# In Oaxaca, the 55.000 teachers from the Section 22 of the National
+# Syndicate of Education Workers, refuse to apply daylight saving each
+# year, so that the more than 10,000 schools work at normal hour the
+# whole year.
+
+# From Gwillim Law (2001-01-19):
+# <http://www.reforma.com/negocios_y_dinero/articulo/064481/> ... says
+# (translated):...
+# January 17, 2000 - The Energy Secretary, Ernesto Martens, announced
+# that Summer Time will be reduced from seven to five months, starting
+# this year....
+# <http://www.publico.com.mx/scripts/texto3.asp?action=pagina&pag=21&pos=p&secc=naci&date=01/17/2001>
+# [translated], says "summer time will ... take effect on the first Sunday
+# in May, and end on the last Sunday of September.
+
+# From Arthur David Olson (2001-01-25):
+# The 2001-01-24 traditional Washington Post contained the page one
+# story "Timely Issue Divides Mexicans."...
+# http://www.washingtonpost.com/wp-dyn/articles/A37383-2001Jan23.html
+# ... Mexico City Mayor Lopez Obrador "...is threatening to keep
+# Mexico City and its 20 million residents on a different time than
+# the rest of the country..." In particular, Lopez Obrador would abolish
+# observation of Daylight Saving Time.
+
+# <a href="http://www.conae.gob.mx/ahorro/decretohorver2001.html#decre">
+# Official statute published by the Energy Department
+# </a> (2001-02-01) shows Baja and Chihauhua as still using US DST rules,
+# and Sonora with no DST. This was reported by Jesper Norgaard (2001-02-03).
+
+# From Paul Eggert (2001-03-03):
+#
+# <a href="http://www.latimes.com/news/nation/20010303/t000018766.html">
+# James F. Smith writes in today's LA Times
+# </a>
+# * Sonora will continue to observe standard time.
+# * Last week Mexico City's mayor Andres Manuel Lopez Obrador decreed that
+# the Federal District will not adopt DST.
+# * 4 of 16 district leaders announced they'll ignore the decree.
+# * The decree does not affect federal-controlled facilities including
+# the airport, banks, hospitals, and schools.
+#
+# For now we'll assume that the Federal District will bow to federal rules.
+
+# From Jesper Norgaard (2001-04-01):
+# I found some references to the Mexican application of daylight
+# saving, which modifies what I had already sent you, stating earlier
+# that a number of northern Mexican states would go on daylight
+# saving. The modification reverts this to only cover Baja California
+# (Norte), while all other states (except Sonora, who has no daylight
+# saving all year) will follow the original decree of president
+# Vicente Fox, starting daylight saving May 6, 2001 and ending
+# September 30, 2001.
+# References: "Diario de Monterrey" <www.diariodemonterrey.com/index.asp>
+# Palabra <http://palabra.infosel.com/010331/primera/ppri3101.pdf> (2001-03-31)
+
+# From Reuters (2001-09-04):
+# Mexico's Supreme Court on Tuesday declared that daylight savings was
+# unconstitutional in Mexico City, creating the possibility the
+# capital will be in a different time zone from the rest of the nation
+# next year.... The Supreme Court's ruling takes effect at 2:00
+# a.m. (0800 GMT) on Sept. 30, when Mexico is scheduled to revert to
+# standard time. "This is so residents of the Federal District are not
+# subject to unexpected time changes," a statement from the court said.
+
+# From Jesper Norgaard Welen (2002-03-12):
+# ... consulting my local grocery store(!) and my coworkers, they all insisted
+# that a new decision had been made to reinstate US style DST in Mexico....
+# http://www.conae.gob.mx/ahorro/horaver2001_m1_2002.html (2002-02-20)
+# confirms this. Sonora as usual is the only state where DST is not applied.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Mexico 1939 only - Feb 5 0:00 1:00 D
+Rule Mexico 1939 only - Jun 25 0:00 0 S
+Rule Mexico 1940 only - Dec 9 0:00 1:00 D
+Rule Mexico 1941 only - Apr 1 0:00 0 S
+Rule Mexico 1943 only - Dec 16 0:00 1:00 W # War
+Rule Mexico 1944 only - May 1 0:00 0 S
+Rule Mexico 1950 only - Feb 12 0:00 1:00 D
+Rule Mexico 1950 only - Jul 30 0:00 0 S
+Rule Mexico 1996 2000 - Apr Sun>=1 2:00 1:00 D
+Rule Mexico 1996 2000 - Oct lastSun 2:00 0 S
+Rule Mexico 2001 only - May Sun>=1 2:00 1:00 D
+Rule Mexico 2001 only - Sep lastSun 2:00 0 S
+Rule Mexico 2002 max - Apr Sun>=1 2:00 1:00 D
+Rule Mexico 2002 max - Oct lastSun 2:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Quintana Roo
+Zone America/Cancun -5:47:04 - LMT 1922 Jan 1 0:12:56
+ -6:00 - CST 1981 Dec 23
+ -5:00 Mexico E%sT 1998 Aug 2 2:00
+ -6:00 Mexico C%sT
+# Campeche, Yucatan
+Zone America/Merida -5:58:28 - LMT 1922 Jan 1 0:01:32
+ -6:00 - CST 1981 Dec 23
+ -5:00 - EST 1982 Dec 2
+ -6:00 Mexico C%sT
+# Coahuila, Durango, Nuevo Leon, Tamaulipas
+Zone America/Monterrey -6:41:16 - LMT 1921 Dec 31 23:18:44
+ -6:00 - CST 1988
+ -6:00 US C%sT 1989
+ -6:00 Mexico C%sT
+# Central Mexico
+Zone America/Mexico_City -6:36:36 - LMT 1922 Jan 1 0:23:24
+ -7:00 - MST 1927 Jun 10 23:00
+ -6:00 - CST 1930 Nov 15
+ -7:00 - MST 1931 May 1 23:00
+ -6:00 - CST 1931 Oct
+ -7:00 - MST 1932 Apr 1
+ -6:00 Mexico C%sT 2001 Sep 30 02:00
+ -6:00 - CST 2002 Feb 20
+ -6:00 Mexico C%sT
+# Chihuahua
+Zone America/Chihuahua -7:04:20 - LMT 1921 Dec 31 23:55:40
+ -7:00 - MST 1927 Jun 10 23:00
+ -6:00 - CST 1930 Nov 15
+ -7:00 - MST 1931 May 1 23:00
+ -6:00 - CST 1931 Oct
+ -7:00 - MST 1932 Apr 1
+ -6:00 - CST 1996
+ -6:00 Mexico C%sT 1998
+ -6:00 - CST 1998 Apr Sun>=1 3:00
+ -7:00 Mexico M%sT
+# Sonora
+Zone America/Hermosillo -7:23:52 - LMT 1921 Dec 31 23:36:08
+ -7:00 - MST 1927 Jun 10 23:00
+ -6:00 - CST 1930 Nov 15
+ -7:00 - MST 1931 May 1 23:00
+ -6:00 - CST 1931 Oct
+ -7:00 - MST 1932 Apr 1
+ -6:00 - CST 1942 Apr 24
+ -7:00 - MST 1949 Jan 14
+ -8:00 - PST 1970
+ -7:00 Mexico M%sT 1999
+ -7:00 - MST
+# Baja California Sur, Nayarit, Sinaloa
+Zone America/Mazatlan -7:05:40 - LMT 1921 Dec 31 23:54:20
+ -7:00 - MST 1927 Jun 10 23:00
+ -6:00 - CST 1930 Nov 15
+ -7:00 - MST 1931 May 1 23:00
+ -6:00 - CST 1931 Oct
+ -7:00 - MST 1932 Apr 1
+ -6:00 - CST 1942 Apr 24
+ -7:00 - MST 1949 Jan 14
+ -8:00 - PST 1970
+ -7:00 Mexico M%sT
+# Baja California
+Zone America/Tijuana -7:48:04 - LMT 1922 Jan 1 0:11:56
+ -7:00 - MST 1924
+ -8:00 - PST 1927 Jun 10 23:00
+ -7:00 - MST 1930 Nov 15
+ -8:00 - PST 1931 Apr 1
+ -8:00 1:00 PDT 1931 Sep 30
+ -8:00 - PST 1942 Apr 24
+ -8:00 1:00 PWT 1945 Aug 14 23:00u
+ -8:00 1:00 PPT 1945 Nov 12 # Peace
+ -8:00 - PST 1948 Apr 5
+ -8:00 1:00 PDT 1949 Jan 14
+ -8:00 - PST 1954
+ -8:00 CA P%sT 1961
+ -8:00 - PST 1976
+ -8:00 US P%sT 1996
+ -8:00 Mexico P%sT 2001
+ -8:00 US P%sT 2002 Feb 20
+ -8:00 Mexico P%sT
+# From Paul Eggert (2006-03-22):
+# Formerly there was an America/Ensenada zone, which differed from
+# America/Tijuana only in that it did not observe DST from 1976
+# through 1995. This was as per Shanks (1999). But Shanks & Pottenger say
+# Ensenada did not observe DST from 1948 through 1975. Guy Harris reports
+# that the 1987 OAG says "Only Ensenada, Mexicale, San Felipe and
+# Tijuana observe DST," which agrees with Shanks & Pottenger but implies that
+# DST-observance was a town-by-town matter back then. This concerns
+# data after 1970 so most likely there should be at least one Zone
+# other than America/Tijuana for Baja, but it's not clear yet what its
+# name or contents should be.
+#
+# Revillagigedo Is
+# no information
+
+###############################################################################
+
+# Anguilla
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Anguilla -4:12:16 - LMT 1912 Mar 2
+ -4:00 - AST
+
+# Antigua and Barbuda
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Antigua -4:07:12 - LMT 1912 Mar 2
+ -5:00 - EST 1951
+ -4:00 - AST
+
+# Bahamas
+#
+# From Sue Williams (2006-12-07):
+# The Bahamas announced about a month ago that they plan to change their DST
+# rules to sync with the U.S. starting in 2007....
+# http://www.jonesbahamas.com/?c=45&a=10412
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Bahamas 1964 1975 - Oct lastSun 2:00 0 S
+Rule Bahamas 1964 1975 - Apr lastSun 2:00 1:00 D
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Nassau -5:09:24 - LMT 1912 Mar 2
+ -5:00 Bahamas E%sT 1976
+ -5:00 US E%sT
+
+# Barbados
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Barb 1977 only - Jun 12 2:00 1:00 D
+Rule Barb 1977 1978 - Oct Sun>=1 2:00 0 S
+Rule Barb 1978 1980 - Apr Sun>=15 2:00 1:00 D
+Rule Barb 1979 only - Sep 30 2:00 0 S
+Rule Barb 1980 only - Sep 25 2:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Barbados -3:58:28 - LMT 1924 # Bridgetown
+ -3:58:28 - BMT 1932 # Bridgetown Mean Time
+ -4:00 Barb A%sT
+
+# Belize
+# Whitman entirely disagrees with Shanks; go with Shanks & Pottenger.
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Belize 1918 1942 - Oct Sun>=2 0:00 0:30 HD
+Rule Belize 1919 1943 - Feb Sun>=9 0:00 0 S
+Rule Belize 1973 only - Dec 5 0:00 1:00 D
+Rule Belize 1974 only - Feb 9 0:00 0 S
+Rule Belize 1982 only - Dec 18 0:00 1:00 D
+Rule Belize 1983 only - Feb 12 0:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Belize -5:52:48 - LMT 1912 Apr
+ -6:00 Belize C%sT
+
+# Bermuda
+
+# From Dan Jones, reporting in The Royal Gazette (2006-06-26):
+
+# Next year, however, clocks in the US will go forward on the second Sunday
+# in March, until the first Sunday in November. And, after the Time Zone
+# (Seasonal Variation) Bill 2006 was passed in the House of Assembly on
+# Friday, the same thing will happen in Bermuda.
+# http://www.theroyalgazette.com/apps/pbcs.dll/article?AID=/20060529/NEWS/105290135
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Atlantic/Bermuda -4:19:04 - LMT 1930 Jan 1 2:00 # Hamilton
+ -4:00 - AST 1974 Apr 28 2:00
+ -4:00 Bahamas A%sT 1976
+ -4:00 US A%sT
+
+# Cayman Is
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Cayman -5:25:32 - LMT 1890 # Georgetown
+ -5:07:12 - KMT 1912 Feb # Kingston Mean Time
+ -5:00 - EST
+
+# Costa Rica
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule CR 1979 1980 - Feb lastSun 0:00 1:00 D
+Rule CR 1979 1980 - Jun Sun>=1 0:00 0 S
+Rule CR 1991 1992 - Jan Sat>=15 0:00 1:00 D
+# IATA SSIM (1991-09) says the following was at 1:00;
+# go with Shanks & Pottenger.
+Rule CR 1991 only - Jul 1 0:00 0 S
+Rule CR 1992 only - Mar 15 0:00 0 S
+# There are too many San Joses elsewhere, so we'll use `Costa Rica'.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Costa_Rica -5:36:20 - LMT 1890 # San Jose
+ -5:36:20 - SJMT 1921 Jan 15 # San Jose Mean Time
+ -6:00 CR C%sT
+# Coco
+# no information; probably like America/Costa_Rica
+
+# Cuba
+
+# From Arthur David Olson (1999-03-29):
+# The 1999-03-28 exhibition baseball game held in Havana, Cuba, between
+# the Cuban National Team and the Baltimore Orioles was carried live on
+# the Orioles Radio Network, including affiliate WTOP in Washington, DC.
+# During the game, play-by-play announcer Jim Hunter noted that
+# "We'll be losing two hours of sleep...Cuba switched to Daylight Saving
+# Time today." (The "two hour" remark referred to losing one hour of
+# sleep on 1999-03-28--when the announcers were in Cuba as it switched
+# to DST--and one more hour on 1999-04-04--when the announcers will have
+# returned to Baltimore, which switches on that date.)
+
+# From Evert van der Veer via Steffen Thorsen (2004-10-28):
+# Cuba is not going back to standard time this year.
+# From Paul Eggert (2006-03-22):
+# http://www.granma.cu/ingles/2004/septiembre/juev30/41medid-i.html
+# says that it's due to a problem at the Antonio Guiteras
+# thermoelectric plant, and says "This October there will be no return
+# to normal hours (after daylight saving time)".
+# For now, let's assume that it's a temporary measure.
+
+# From Carlos A. Carnero Delgado (2005-11-12):
+# This year (just like in 2004-2005) there's no change in time zone
+# adjustment in Cuba. We will stay in daylight saving time:
+# http://www.granma.cu/espanol/2005/noviembre/mier9/horario.html
+
+# From Jesper Norgaard Welen (2006-10-21):
+# An article in GRANMA INTERNACIONAL claims that Cuba will end
+# the 3 years of permanent DST next weekend, see
+# http://www.granma.cu/ingles/2006/octubre/lun16/43horario.html
+# "On Saturday night, October 28 going into Sunday, October 29, at 01:00,
+# watches should be set back one hour -- going back to 00:00 hours -- returning
+# to the normal schedule....
+
+# From Paul Eggert (2007-03-02):
+# http://www.granma.cubaweb.cu/english/news/art89.html, dated yesterday,
+# says Cuban clocks will advance at midnight on March 10.
+# For lack of better information, assume Cuba will use US rules,
+# except that it switches at midnight standard time as usual.
+#
+# From Steffen Thorsen (2007-10-25):
+# Carlos Alberto Fonseca Arauz informed me that Cuba will end DST one week
+# earlier - on the last Sunday of October, just like in 2006.
+#
+# He supplied these references:
+#
+# http://www.prensalatina.com.mx/article.asp?ID=%7B4CC32C1B-A9F7-42FB-8A07-8631AFC923AF%7D&language=ES
+# http://actualidad.terra.es/sociedad/articulo/cuba_llama_ahorrar_energia_cambio_1957044.htm
+#
+# From Alex Kryvenishev (2007-10-25):
+# Here is also article from Granma (Cuba):
+#
+# [Regira] el Horario Normal desde el [proximo] domingo 28 de octubre
+# http://www.granma.cubaweb.cu/2007/10/24/nacional/artic07.html
+#
+# http://www.worldtimezone.com/dst_news/dst_news_cuba03.html
+
+# From Arthur David Olson (2008-03-09):
+# I'm in Maryland which is now observing United States Eastern Daylight
+# Time. At 9:44 local time I used RealPlayer to listen to
+# <a href="http://media.enet.cu/radioreloj">
+# http://media.enet.cu/radioreloj
+# </a>, a Cuban information station, and heard
+# the time announced as "ocho cuarenta y cuatro" ("eight forty-four"),
+# indicating that Cuba is still on standard time.
+
+# From Steffen Thorsen (2008-03-12):
+# It seems that Cuba will start DST on Sunday, 2007-03-16...
+# It was announced yesterday, according to this source (in Spanish):
+# <a href="http://www.nnc.cubaweb.cu/marzo-2008/cien-1-11-3-08.htm">
+# http://www.nnc.cubaweb.cu/marzo-2008/cien-1-11-3-08.htm
+# </a>
+#
+# Some more background information is posted here:
+# <a href="http://www.timeanddate.com/news/time/cuba-starts-dst-march-16.html">
+# http://www.timeanddate.com/news/time/cuba-starts-dst-march-16.html
+# </a>
+#
+# The article also says that Cuba has been observing DST since 1963,
+# while Shanks (and tzdata) has 1965 as the first date (except in the
+# 1940's). Many other web pages in Cuba also claim that it has been
+# observed since 1963, but with the exception of 1970 - an exception
+# which is not present in tzdata/Shanks. So there is a chance we need to
+# change some historic records as well.
+#
+# One example:
+# <a href="http://www.radiohc.cu/espanol/noticias/mar07/11mar/hor.htm">
+# http://www.radiohc.cu/espanol/noticias/mar07/11mar/hor.htm
+# </a>
+
+# From Jesper Norgaard Welen (2008-03-13):
+# The Cuban time change has just been confirmed on the most authoritative
+# web site, the Granma. Please check out
+# <a href="http://www.granma.cubaweb.cu/2008/03/13/nacional/artic10.html">
+# http://www.granma.cubaweb.cu/2008/03/13/nacional/artic10.html
+# </a>
+#
+# Basically as expected after Steffen Thorsens information, the change
+# will take place midnight between Saturday and Sunday.
+
+# From Arthur David Olson (2008-03-12):
+# Assume Sun>=15 (third Sunday) going forward.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Cuba 1928 only - Jun 10 0:00 1:00 D
+Rule Cuba 1928 only - Oct 10 0:00 0 S
+Rule Cuba 1940 1942 - Jun Sun>=1 0:00 1:00 D
+Rule Cuba 1940 1942 - Sep Sun>=1 0:00 0 S
+Rule Cuba 1945 1946 - Jun Sun>=1 0:00 1:00 D
+Rule Cuba 1945 1946 - Sep Sun>=1 0:00 0 S
+Rule Cuba 1965 only - Jun 1 0:00 1:00 D
+Rule Cuba 1965 only - Sep 30 0:00 0 S
+Rule Cuba 1966 only - May 29 0:00 1:00 D
+Rule Cuba 1966 only - Oct 2 0:00 0 S
+Rule Cuba 1967 only - Apr 8 0:00 1:00 D
+Rule Cuba 1967 1968 - Sep Sun>=8 0:00 0 S
+Rule Cuba 1968 only - Apr 14 0:00 1:00 D
+Rule Cuba 1969 1977 - Apr lastSun 0:00 1:00 D
+Rule Cuba 1969 1971 - Oct lastSun 0:00 0 S
+Rule Cuba 1972 1974 - Oct 8 0:00 0 S
+Rule Cuba 1975 1977 - Oct lastSun 0:00 0 S
+Rule Cuba 1978 only - May 7 0:00 1:00 D
+Rule Cuba 1978 1990 - Oct Sun>=8 0:00 0 S
+Rule Cuba 1979 1980 - Mar Sun>=15 0:00 1:00 D
+Rule Cuba 1981 1985 - May Sun>=5 0:00 1:00 D
+Rule Cuba 1986 1989 - Mar Sun>=14 0:00 1:00 D
+Rule Cuba 1990 1997 - Apr Sun>=1 0:00 1:00 D
+Rule Cuba 1991 1995 - Oct Sun>=8 0:00s 0 S
+Rule Cuba 1996 only - Oct 6 0:00s 0 S
+Rule Cuba 1997 only - Oct 12 0:00s 0 S
+Rule Cuba 1998 1999 - Mar lastSun 0:00s 1:00 D
+Rule Cuba 1998 2003 - Oct lastSun 0:00s 0 S
+Rule Cuba 2000 2006 - Apr Sun>=1 0:00s 1:00 D
+Rule Cuba 2006 max - Oct lastSun 0:00s 0 S
+Rule Cuba 2007 only - Mar Sun>=8 0:00s 1:00 D
+Rule Cuba 2008 max - Mar Sun>=15 0:00s 1:00 D
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Havana -5:29:28 - LMT 1890
+ -5:29:36 - HMT 1925 Jul 19 12:00 # Havana MT
+ -5:00 Cuba C%sT
+
+# Dominica
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Dominica -4:05:36 - LMT 1911 Jul 1 0:01 # Roseau
+ -4:00 - AST
+
+# Dominican Republic
+
+# From Steffen Thorsen (2000-10-30):
+# Enrique Morales reported to me that the Dominican Republic has changed the
+# time zone to Eastern Standard Time as of Sunday 29 at 2 am....
+# http://www.listin.com.do/antes/261000/republica/princi.html
+
+# From Paul Eggert (2000-12-04):
+# That URL (2000-10-26, in Spanish) says they planned to use US-style DST.
+
+# From Rives McDow (2000-12-01):
+# Dominican Republic changed its mind and presidential decree on Tuesday,
+# November 28, 2000, with a new decree. On Sunday, December 3 at 1:00 AM the
+# Dominican Republic will be reverting to 8 hours from the International Date
+# Line, and will not be using DST in the foreseeable future. The reason they
+# decided to use DST was to be in synch with Puerto Rico, who was also going
+# to implement DST. When Puerto Rico didn't implement DST, the president
+# decided to revert.
+
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule DR 1966 only - Oct 30 0:00 1:00 D
+Rule DR 1967 only - Feb 28 0:00 0 S
+Rule DR 1969 1973 - Oct lastSun 0:00 0:30 HD
+Rule DR 1970 only - Feb 21 0:00 0 S
+Rule DR 1971 only - Jan 20 0:00 0 S
+Rule DR 1972 1974 - Jan 21 0:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Santo_Domingo -4:39:36 - LMT 1890
+ -4:40 - SDMT 1933 Apr 1 12:00 # S. Dom. MT
+ -5:00 DR E%sT 1974 Oct 27
+ -4:00 - AST 2000 Oct 29 02:00
+ -5:00 US E%sT 2000 Dec 3 01:00
+ -4:00 - AST
+
+# El Salvador
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Salv 1987 1988 - May Sun>=1 0:00 1:00 D
+Rule Salv 1987 1988 - Sep lastSun 0:00 0 S
+# There are too many San Salvadors elsewhere, so use America/El_Salvador
+# instead of America/San_Salvador.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/El_Salvador -5:56:48 - LMT 1921 # San Salvador
+ -6:00 Salv C%sT
+
+# Grenada
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Grenada -4:07:00 - LMT 1911 Jul # St George's
+ -4:00 - AST
+
+# Guadeloupe
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Guadeloupe -4:06:08 - LMT 1911 Jun 8 # Pointe a Pitre
+ -4:00 - AST
+# St Barthelemy
+Link America/Guadeloupe America/St_Barthelemy
+# St Martin (French part)
+Link America/Guadeloupe America/Marigot
+
+# Guatemala
+#
+# From Gwillim Law (2006-04-22), after a heads-up from Oscar van Vlijmen:
+# Diario Co Latino, at
+# http://www.diariocolatino.com/internacionales/detalles.asp?NewsID=8079,
+# says in an article dated 2006-04-19 that the Guatemalan government had
+# decided on that date to advance official time by 60 minutes, to lessen the
+# impact of the elevated cost of oil.... Daylight saving time will last from
+# 2006-04-29 24:00 (Guatemalan standard time) to 2006-09-30 (time unspecified).
+# From Paul Eggert (2006-06-22):
+# The Ministry of Energy and Mines, press release CP-15/2006
+# (2006-04-19), says DST ends at 24:00. See
+# <http://www.sieca.org.gt/Sitio_publico/Energeticos/Doc/Medidas/Cambio_Horario_Nac_190406.pdf>.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Guat 1973 only - Nov 25 0:00 1:00 D
+Rule Guat 1974 only - Feb 24 0:00 0 S
+Rule Guat 1983 only - May 21 0:00 1:00 D
+Rule Guat 1983 only - Sep 22 0:00 0 S
+Rule Guat 1991 only - Mar 23 0:00 1:00 D
+Rule Guat 1991 only - Sep 7 0:00 0 S
+Rule Guat 2006 only - Apr 30 0:00 1:00 D
+Rule Guat 2006 only - Oct 1 0:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Guatemala -6:02:04 - LMT 1918 Oct 5
+ -6:00 Guat C%sT
+
+# Haiti
+# From Gwillim Law (2005-04-15):
+# Risto O. Nykanen wrote me that Haiti is now on DST.
+# I searched for confirmation, and I found a
+# <a href="http://www.haitianconsulate.org/time.doc"> press release
+# on the Web page of the Haitian Consulate in Chicago (2005-03-31),
+# </a>. Translated from French, it says:
+#
+# "The Prime Minister's Communication Office notifies the public in general
+# and the press in particular that, following a decision of the Interior
+# Ministry and the Territorial Collectivities [I suppose that means the
+# provinces], Haiti will move to Eastern Daylight Time in the night from next
+# Saturday the 2nd to Sunday the 3rd.
+#
+# "Consequently, the Prime Minister's Communication Office wishes to inform
+# the population that the country's clocks will be set forward one hour
+# starting at midnight. This provision will hold until the last Saturday in
+# October 2005.
+#
+# "Port-au-Prince, March 31, 2005"
+#
+# From Steffen Thorsen (2006-04-04):
+# I have been informed by users that Haiti observes DST this year like
+# last year, so the current "only" rule for 2005 might be changed to a
+# "max" rule or to last until 2006. (Who knows if they will observe DST
+# next year or if they will extend their DST like US/Canada next year).
+#
+# I have found this article about it (in French):
+# http://www.haitipressnetwork.com/news.cfm?articleID=7612
+#
+# The reason seems to be an energy crisis.
+
+# From Stephen Colebourne (2007-02-22):
+# Some IATA info: Haiti won't be having DST in 2007.
+
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Haiti 1983 only - May 8 0:00 1:00 D
+Rule Haiti 1984 1987 - Apr lastSun 0:00 1:00 D
+Rule Haiti 1983 1987 - Oct lastSun 0:00 0 S
+# Shanks & Pottenger say AT is 2:00, but IATA SSIM (1991/1997) says 1:00s.
+# Go with IATA.
+Rule Haiti 1988 1997 - Apr Sun>=1 1:00s 1:00 D
+Rule Haiti 1988 1997 - Oct lastSun 1:00s 0 S
+Rule Haiti 2005 2006 - Apr Sun>=1 0:00 1:00 D
+Rule Haiti 2005 2006 - Oct lastSun 0:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Port-au-Prince -4:49:20 - LMT 1890
+ -4:49 - PPMT 1917 Jan 24 12:00 # P-a-P MT
+ -5:00 Haiti E%sT
+
+# Honduras
+# Shanks & Pottenger say 1921 Jan 1; go with Whitman's more precise Apr 1.
+
+# From Paul Eggert (2006-05-05):
+# worldtimezone.com reports a 2006-05-02 Spanish-language AP article
+# saying Honduras will start using DST midnight Saturday, effective 4
+# months until September. La Tribuna reported today
+# <http://www.latribuna.hn/99299.html> that Manuel Zelaya, the president
+# of Honduras, refused to back down on this.
+
+# From Jesper Norgaard Welen (2006-08-08):
+# It seems that Honduras has returned from DST to standard time this Monday at
+# 00:00 hours (prolonging Sunday to 25 hours duration).
+# http://www.worldtimezone.com/dst_news/dst_news_honduras04.html
+
+# From Paul Eggert (2006-08-08):
+# Also see Diario El Heraldo, The country returns to standard time (2006-08-08)
+# <http://www.elheraldo.hn/nota.php?nid=54941&sec=12>.
+# It mentions executive decree 18-2006.
+
+# From Steffen Thorsen (2006-08-17):
+# Honduras will observe DST from 2007 to 2009, exact dates are not
+# published, I have located this authoritative source:
+# http://www.presidencia.gob.hn/noticia.aspx?nId=47
+
+# From Steffen Thorsen (2007-03-30):
+# http://www.laprensahn.com/pais_nota.php?id04962=7386
+# So it seems that Honduras will not enter DST this year....
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Hond 1987 1988 - May Sun>=1 0:00 1:00 D
+Rule Hond 1987 1988 - Sep lastSun 0:00 0 S
+Rule Hond 2006 only - May Sun>=1 0:00 1:00 D
+Rule Hond 2006 only - Aug Mon>=1 0:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Tegucigalpa -5:48:52 - LMT 1921 Apr
+ -6:00 Hond C%sT
+#
+# Great Swan I ceded by US to Honduras in 1972
+
+# Jamaica
+
+# From Bob Devine (1988-01-28):
+# Follows US rules.
+
+# From U. S. Naval Observatory (1989-01-19):
+# JAMAICA 5 H BEHIND UTC
+
+# From Shanks & Pottenger:
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Jamaica -5:07:12 - LMT 1890 # Kingston
+ -5:07:12 - KMT 1912 Feb # Kingston Mean Time
+ -5:00 - EST 1974 Apr 28 2:00
+ -5:00 US E%sT 1984
+ -5:00 - EST
+
+# Martinique
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Martinique -4:04:20 - LMT 1890 # Fort-de-France
+ -4:04:20 - FFMT 1911 May # Fort-de-France MT
+ -4:00 - AST 1980 Apr 6
+ -4:00 1:00 ADT 1980 Sep 28
+ -4:00 - AST
+
+# Montserrat
+# From Paul Eggert (2006-03-22):
+# In 1995 volcanic eruptions forced evacuation of Plymouth, the capital.
+# world.gazetteer.com says Cork Hill is the most populous location now.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Montserrat -4:08:52 - LMT 1911 Jul 1 0:01 # Cork Hill
+ -4:00 - AST
+
+# Nicaragua
+#
+# This uses Shanks & Pottenger for times before 2005.
+#
+# From Steffen Thorsen (2005-04-12):
+# I've got reports from 8 different people that Nicaragua just started
+# DST on Sunday 2005-04-10, in order to save energy because of
+# expensive petroleum. The exact end date for DST is not yet
+# announced, only "September" but some sites also say "mid-September".
+# Some background information is available on the President's official site:
+# http://www.presidencia.gob.ni/Presidencia/Files_index/Secretaria/Notas%20de%20Prensa/Presidente/2005/ABRIL/Gobierno-de-nicaragua-adelanta-hora-oficial-06abril.htm
+# The Decree, no 23-2005 is available here:
+# http://www.presidencia.gob.ni/buscador_gaceta/BD/DECRETOS/2005/Decreto%2023-2005%20Se%20adelanta%20en%20una%20hora%20en%20todo%20el%20territorio%20nacional%20apartir%20de%20las%2024horas%20del%2009%20de%20Abril.pdf
+#
+# From Paul Eggert (2005-05-01):
+# The decree doesn't say anything about daylight saving, but for now let's
+# assume that it is daylight saving....
+#
+# From Gwillim Law (2005-04-21):
+# The Associated Press story on the time change, which can be found at
+# http://www.lapalmainteractivo.com/guias/content/gen/ap/America_Latina/AMC_GEN_NICARAGUA_HORA.html
+# and elsewhere, says (fifth paragraph, translated from Spanish): "The last
+# time that a change of clocks was applied to save energy was in the year 2000
+# during the Arnoldo Aleman administration."...
+# The northamerica file says that Nicaragua has been on UTC-6 continuously
+# since December 1998. I wasn't able to find any details of Nicaraguan time
+# changes in 2000. Perhaps a note could be added to the northamerica file, to
+# the effect that we have indirect evidence that DST was observed in 2000.
+#
+# From Jesper Norgaard Welen (2005-11-02):
+# Nicaragua left DST the 2005-10-02 at 00:00 (local time).
+# http://www.presidencia.gob.ni/presidencia/files_index/secretaria/comunicados/2005/septiembre/26septiembre-cambio-hora.htm
+# (2005-09-26)
+#
+# From Jesper Norgaard Welen (2006-05-05):
+# http://www.elnuevodiario.com.ni/2006/05/01/nacionales/18410
+# (my informal translation)
+# By order of the president of the republic, Enrique Bolanos, Nicaragua
+# advanced by sixty minutes their official time, yesterday at 2 in the
+# morning, and will stay that way until 30.th. of september.
+#
+# From Jesper Norgaard Welen (2006-09-30):
+# http://www.presidencia.gob.ni/buscador_gaceta/BD/DECRETOS/2006/D-063-2006P-PRN-Cambio-Hora.pdf
+# My informal translation runs:
+# The natural sun time is restored in all the national territory, in that the
+# time is returned one hour at 01:00 am of October 1 of 2006.
+#
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Nic 1979 1980 - Mar Sun>=16 0:00 1:00 D
+Rule Nic 1979 1980 - Jun Mon>=23 0:00 0 S
+Rule Nic 2005 only - Apr 10 0:00 1:00 D
+Rule Nic 2005 only - Oct Sun>=1 0:00 0 S
+Rule Nic 2006 only - Apr 30 2:00 1:00 D
+Rule Nic 2006 only - Oct Sun>=1 1:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Managua -5:45:08 - LMT 1890
+ -5:45:12 - MMT 1934 Jun 23 # Managua Mean Time?
+ -6:00 - CST 1973 May
+ -5:00 - EST 1975 Feb 16
+ -6:00 Nic C%sT 1992 Jan 1 4:00
+ -5:00 - EST 1992 Sep 24
+ -6:00 - CST 1993
+ -5:00 - EST 1997
+ -6:00 Nic C%sT
+
+# Panama
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Panama -5:18:08 - LMT 1890
+ -5:19:36 - CMT 1908 Apr 22 # Colon Mean Time
+ -5:00 - EST
+
+# Puerto Rico
+# There are too many San Juans elsewhere, so we'll use `Puerto_Rico'.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Puerto_Rico -4:24:25 - LMT 1899 Mar 28 12:00 # San Juan
+ -4:00 - AST 1942 May 3
+ -4:00 US A%sT 1946
+ -4:00 - AST
+
+# St Kitts-Nevis
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/St_Kitts -4:10:52 - LMT 1912 Mar 2 # Basseterre
+ -4:00 - AST
+
+# St Lucia
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/St_Lucia -4:04:00 - LMT 1890 # Castries
+ -4:04:00 - CMT 1912 # Castries Mean Time
+ -4:00 - AST
+
+# St Pierre and Miquelon
+# There are too many St Pierres elsewhere, so we'll use `Miquelon'.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Miquelon -3:44:40 - LMT 1911 May 15 # St Pierre
+ -4:00 - AST 1980 May
+ -3:00 - PMST 1987 # Pierre & Miquelon Time
+ -3:00 Canada PM%sT
+
+# St Vincent and the Grenadines
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/St_Vincent -4:04:56 - LMT 1890 # Kingstown
+ -4:04:56 - KMT 1912 # Kingstown Mean Time
+ -4:00 - AST
+
+# Turks and Caicos
+#
+# From Chris Dunn in
+# <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=415007>
+# (2007-03-15): In the Turks & Caicos Islands (America/Grand_Turk) the
+# daylight saving dates for time changes have been adjusted to match
+# the recent U.S. change of dates.
+#
+# From Brian Inglis (2007-04-28):
+# http://www.turksandcaicos.tc/calendar/index.htm [2007-04-26]
+# there is an entry for Nov 4 "Daylight Savings Time Ends 2007" and three
+# rows before that there is an out of date entry for Oct:
+# "Eastern Standard Times Begins 2007
+# Clocks are set back one hour at 2:00 a.m. local Daylight Saving Time"
+# indicating that the normal ET rules are followed.
+#
+# From Paul Eggert (2006-05-01):
+# Shanks & Pottenger say they use US DST rules, but IATA SSIM (1991/1998)
+# says they switch at midnight. Go with Shanks & Pottenger.
+#
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule TC 1979 1986 - Apr lastSun 2:00 1:00 D
+Rule TC 1979 2006 - Oct lastSun 2:00 0 S
+Rule TC 1987 2006 - Apr Sun>=1 2:00 1:00 D
+Rule TC 2007 max - Mar Sun>=8 2:00 1:00 D
+Rule TC 2007 max - Nov Sun>=1 2:00 0 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Grand_Turk -4:44:32 - LMT 1890
+ -5:07:12 - KMT 1912 Feb # Kingston Mean Time
+ -5:00 TC E%sT
+
+# British Virgin Is
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Tortola -4:18:28 - LMT 1911 Jul # Road Town
+ -4:00 - AST
+
+# Virgin Is
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/St_Thomas -4:19:44 - LMT 1911 Jul # Charlotte Amalie
+ -4:00 - AST
diff --git a/tools/zoneinfo/tzdata2008h/pacificnew b/tools/zoneinfo/tzdata2008h/pacificnew
new file mode 100644
index 0000000..667940b
--- /dev/null
+++ b/tools/zoneinfo/tzdata2008h/pacificnew
@@ -0,0 +1,26 @@
+# @(#)pacificnew 8.1
+
+# From Arthur David Olson (1989-04-05):
+# On 1989-04-05, the U. S. House of Representatives passed (238-154) a bill
+# establishing "Pacific Presidential Election Time"; it was not acted on
+# by the Senate or signed into law by the President.
+# You might want to change the "PE" (Presidential Election) below to
+# "Q" (Quadrennial) to maintain three-character zone abbreviations.
+# If you're really conservative, you might want to change it to "D".
+# Avoid "L" (Leap Year), which won't be true in 2100.
+
+# If Presidential Election Time is ever established, replace "XXXX" below
+# with the year the law takes effect and uncomment the "##" lines.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+## Rule Twilite XXXX max - Apr Sun>=1 2:00 1:00 D
+## Rule Twilite XXXX max uspres Oct lastSun 2:00 1:00 PE
+## Rule Twilite XXXX max uspres Nov Sun>=7 2:00 0 S
+## Rule Twilite XXXX max nonpres Oct lastSun 2:00 0 S
+
+# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL]
+## Zone America/Los_Angeles-PET -8:00 US P%sT XXXX
+## -8:00 Twilite P%sT
+
+# For now...
+Link America/Los_Angeles US/Pacific-New ##
diff --git a/tools/zoneinfo/tzdata2008h/solar87 b/tools/zoneinfo/tzdata2008h/solar87
new file mode 100644
index 0000000..7183932
--- /dev/null
+++ b/tools/zoneinfo/tzdata2008h/solar87
@@ -0,0 +1,388 @@
+# @(#)solar87 8.1
+
+# So much for footnotes about Saudi Arabia.
+# Apparent noon times below are for Riyadh; your mileage will vary.
+# Times were computed using formulas in the U.S. Naval Observatory's
+# Almanac for Computers 1987; the formulas "will give EqT to an accuracy of
+# [plus or minus two] seconds during the current year."
+#
+# Rounding to the nearest five seconds results in fewer than
+# 256 different "time types"--a limit that's faced because time types are
+# stored on disk as unsigned chars.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule sol87 1987 only - Jan 1 12:03:20s -0:03:20 -
+Rule sol87 1987 only - Jan 2 12:03:50s -0:03:50 -
+Rule sol87 1987 only - Jan 3 12:04:15s -0:04:15 -
+Rule sol87 1987 only - Jan 4 12:04:45s -0:04:45 -
+Rule sol87 1987 only - Jan 5 12:05:10s -0:05:10 -
+Rule sol87 1987 only - Jan 6 12:05:40s -0:05:40 -
+Rule sol87 1987 only - Jan 7 12:06:05s -0:06:05 -
+Rule sol87 1987 only - Jan 8 12:06:30s -0:06:30 -
+Rule sol87 1987 only - Jan 9 12:06:55s -0:06:55 -
+Rule sol87 1987 only - Jan 10 12:07:20s -0:07:20 -
+Rule sol87 1987 only - Jan 11 12:07:45s -0:07:45 -
+Rule sol87 1987 only - Jan 12 12:08:10s -0:08:10 -
+Rule sol87 1987 only - Jan 13 12:08:30s -0:08:30 -
+Rule sol87 1987 only - Jan 14 12:08:55s -0:08:55 -
+Rule sol87 1987 only - Jan 15 12:09:15s -0:09:15 -
+Rule sol87 1987 only - Jan 16 12:09:35s -0:09:35 -
+Rule sol87 1987 only - Jan 17 12:09:55s -0:09:55 -
+Rule sol87 1987 only - Jan 18 12:10:15s -0:10:15 -
+Rule sol87 1987 only - Jan 19 12:10:35s -0:10:35 -
+Rule sol87 1987 only - Jan 20 12:10:55s -0:10:55 -
+Rule sol87 1987 only - Jan 21 12:11:10s -0:11:10 -
+Rule sol87 1987 only - Jan 22 12:11:30s -0:11:30 -
+Rule sol87 1987 only - Jan 23 12:11:45s -0:11:45 -
+Rule sol87 1987 only - Jan 24 12:12:00s -0:12:00 -
+Rule sol87 1987 only - Jan 25 12:12:15s -0:12:15 -
+Rule sol87 1987 only - Jan 26 12:12:30s -0:12:30 -
+Rule sol87 1987 only - Jan 27 12:12:40s -0:12:40 -
+Rule sol87 1987 only - Jan 28 12:12:55s -0:12:55 -
+Rule sol87 1987 only - Jan 29 12:13:05s -0:13:05 -
+Rule sol87 1987 only - Jan 30 12:13:15s -0:13:15 -
+Rule sol87 1987 only - Jan 31 12:13:25s -0:13:25 -
+Rule sol87 1987 only - Feb 1 12:13:35s -0:13:35 -
+Rule sol87 1987 only - Feb 2 12:13:40s -0:13:40 -
+Rule sol87 1987 only - Feb 3 12:13:50s -0:13:50 -
+Rule sol87 1987 only - Feb 4 12:13:55s -0:13:55 -
+Rule sol87 1987 only - Feb 5 12:14:00s -0:14:00 -
+Rule sol87 1987 only - Feb 6 12:14:05s -0:14:05 -
+Rule sol87 1987 only - Feb 7 12:14:10s -0:14:10 -
+Rule sol87 1987 only - Feb 8 12:14:10s -0:14:10 -
+Rule sol87 1987 only - Feb 9 12:14:15s -0:14:15 -
+Rule sol87 1987 only - Feb 10 12:14:15s -0:14:15 -
+Rule sol87 1987 only - Feb 11 12:14:15s -0:14:15 -
+Rule sol87 1987 only - Feb 12 12:14:15s -0:14:15 -
+Rule sol87 1987 only - Feb 13 12:14:15s -0:14:15 -
+Rule sol87 1987 only - Feb 14 12:14:15s -0:14:15 -
+Rule sol87 1987 only - Feb 15 12:14:10s -0:14:10 -
+Rule sol87 1987 only - Feb 16 12:14:10s -0:14:10 -
+Rule sol87 1987 only - Feb 17 12:14:05s -0:14:05 -
+Rule sol87 1987 only - Feb 18 12:14:00s -0:14:00 -
+Rule sol87 1987 only - Feb 19 12:13:55s -0:13:55 -
+Rule sol87 1987 only - Feb 20 12:13:50s -0:13:50 -
+Rule sol87 1987 only - Feb 21 12:13:45s -0:13:45 -
+Rule sol87 1987 only - Feb 22 12:13:35s -0:13:35 -
+Rule sol87 1987 only - Feb 23 12:13:30s -0:13:30 -
+Rule sol87 1987 only - Feb 24 12:13:20s -0:13:20 -
+Rule sol87 1987 only - Feb 25 12:13:10s -0:13:10 -
+Rule sol87 1987 only - Feb 26 12:13:00s -0:13:00 -
+Rule sol87 1987 only - Feb 27 12:12:50s -0:12:50 -
+Rule sol87 1987 only - Feb 28 12:12:40s -0:12:40 -
+Rule sol87 1987 only - Mar 1 12:12:30s -0:12:30 -
+Rule sol87 1987 only - Mar 2 12:12:20s -0:12:20 -
+Rule sol87 1987 only - Mar 3 12:12:05s -0:12:05 -
+Rule sol87 1987 only - Mar 4 12:11:55s -0:11:55 -
+Rule sol87 1987 only - Mar 5 12:11:40s -0:11:40 -
+Rule sol87 1987 only - Mar 6 12:11:25s -0:11:25 -
+Rule sol87 1987 only - Mar 7 12:11:15s -0:11:15 -
+Rule sol87 1987 only - Mar 8 12:11:00s -0:11:00 -
+Rule sol87 1987 only - Mar 9 12:10:45s -0:10:45 -
+Rule sol87 1987 only - Mar 10 12:10:30s -0:10:30 -
+Rule sol87 1987 only - Mar 11 12:10:15s -0:10:15 -
+Rule sol87 1987 only - Mar 12 12:09:55s -0:09:55 -
+Rule sol87 1987 only - Mar 13 12:09:40s -0:09:40 -
+Rule sol87 1987 only - Mar 14 12:09:25s -0:09:25 -
+Rule sol87 1987 only - Mar 15 12:09:10s -0:09:10 -
+Rule sol87 1987 only - Mar 16 12:08:50s -0:08:50 -
+Rule sol87 1987 only - Mar 17 12:08:35s -0:08:35 -
+Rule sol87 1987 only - Mar 18 12:08:15s -0:08:15 -
+Rule sol87 1987 only - Mar 19 12:08:00s -0:08:00 -
+Rule sol87 1987 only - Mar 20 12:07:40s -0:07:40 -
+Rule sol87 1987 only - Mar 21 12:07:25s -0:07:25 -
+Rule sol87 1987 only - Mar 22 12:07:05s -0:07:05 -
+Rule sol87 1987 only - Mar 23 12:06:50s -0:06:50 -
+Rule sol87 1987 only - Mar 24 12:06:30s -0:06:30 -
+Rule sol87 1987 only - Mar 25 12:06:10s -0:06:10 -
+Rule sol87 1987 only - Mar 26 12:05:55s -0:05:55 -
+Rule sol87 1987 only - Mar 27 12:05:35s -0:05:35 -
+Rule sol87 1987 only - Mar 28 12:05:15s -0:05:15 -
+Rule sol87 1987 only - Mar 29 12:05:00s -0:05:00 -
+Rule sol87 1987 only - Mar 30 12:04:40s -0:04:40 -
+Rule sol87 1987 only - Mar 31 12:04:25s -0:04:25 -
+Rule sol87 1987 only - Apr 1 12:04:05s -0:04:05 -
+Rule sol87 1987 only - Apr 2 12:03:45s -0:03:45 -
+Rule sol87 1987 only - Apr 3 12:03:30s -0:03:30 -
+Rule sol87 1987 only - Apr 4 12:03:10s -0:03:10 -
+Rule sol87 1987 only - Apr 5 12:02:55s -0:02:55 -
+Rule sol87 1987 only - Apr 6 12:02:35s -0:02:35 -
+Rule sol87 1987 only - Apr 7 12:02:20s -0:02:20 -
+Rule sol87 1987 only - Apr 8 12:02:05s -0:02:05 -
+Rule sol87 1987 only - Apr 9 12:01:45s -0:01:45 -
+Rule sol87 1987 only - Apr 10 12:01:30s -0:01:30 -
+Rule sol87 1987 only - Apr 11 12:01:15s -0:01:15 -
+Rule sol87 1987 only - Apr 12 12:00:55s -0:00:55 -
+Rule sol87 1987 only - Apr 13 12:00:40s -0:00:40 -
+Rule sol87 1987 only - Apr 14 12:00:25s -0:00:25 -
+Rule sol87 1987 only - Apr 15 12:00:10s -0:00:10 -
+Rule sol87 1987 only - Apr 16 11:59:55s 0:00:05 -
+Rule sol87 1987 only - Apr 17 11:59:45s 0:00:15 -
+Rule sol87 1987 only - Apr 18 11:59:30s 0:00:30 -
+Rule sol87 1987 only - Apr 19 11:59:15s 0:00:45 -
+Rule sol87 1987 only - Apr 20 11:59:05s 0:00:55 -
+Rule sol87 1987 only - Apr 21 11:58:50s 0:01:10 -
+Rule sol87 1987 only - Apr 22 11:58:40s 0:01:20 -
+Rule sol87 1987 only - Apr 23 11:58:25s 0:01:35 -
+Rule sol87 1987 only - Apr 24 11:58:15s 0:01:45 -
+Rule sol87 1987 only - Apr 25 11:58:05s 0:01:55 -
+Rule sol87 1987 only - Apr 26 11:57:55s 0:02:05 -
+Rule sol87 1987 only - Apr 27 11:57:45s 0:02:15 -
+Rule sol87 1987 only - Apr 28 11:57:35s 0:02:25 -
+Rule sol87 1987 only - Apr 29 11:57:25s 0:02:35 -
+Rule sol87 1987 only - Apr 30 11:57:15s 0:02:45 -
+Rule sol87 1987 only - May 1 11:57:10s 0:02:50 -
+Rule sol87 1987 only - May 2 11:57:00s 0:03:00 -
+Rule sol87 1987 only - May 3 11:56:55s 0:03:05 -
+Rule sol87 1987 only - May 4 11:56:50s 0:03:10 -
+Rule sol87 1987 only - May 5 11:56:45s 0:03:15 -
+Rule sol87 1987 only - May 6 11:56:40s 0:03:20 -
+Rule sol87 1987 only - May 7 11:56:35s 0:03:25 -
+Rule sol87 1987 only - May 8 11:56:30s 0:03:30 -
+Rule sol87 1987 only - May 9 11:56:25s 0:03:35 -
+Rule sol87 1987 only - May 10 11:56:25s 0:03:35 -
+Rule sol87 1987 only - May 11 11:56:20s 0:03:40 -
+Rule sol87 1987 only - May 12 11:56:20s 0:03:40 -
+Rule sol87 1987 only - May 13 11:56:20s 0:03:40 -
+Rule sol87 1987 only - May 14 11:56:20s 0:03:40 -
+Rule sol87 1987 only - May 15 11:56:20s 0:03:40 -
+Rule sol87 1987 only - May 16 11:56:20s 0:03:40 -
+Rule sol87 1987 only - May 17 11:56:20s 0:03:40 -
+Rule sol87 1987 only - May 18 11:56:20s 0:03:40 -
+Rule sol87 1987 only - May 19 11:56:25s 0:03:35 -
+Rule sol87 1987 only - May 20 11:56:25s 0:03:35 -
+Rule sol87 1987 only - May 21 11:56:30s 0:03:30 -
+Rule sol87 1987 only - May 22 11:56:35s 0:03:25 -
+Rule sol87 1987 only - May 23 11:56:40s 0:03:20 -
+Rule sol87 1987 only - May 24 11:56:45s 0:03:15 -
+Rule sol87 1987 only - May 25 11:56:50s 0:03:10 -
+Rule sol87 1987 only - May 26 11:56:55s 0:03:05 -
+Rule sol87 1987 only - May 27 11:57:00s 0:03:00 -
+Rule sol87 1987 only - May 28 11:57:10s 0:02:50 -
+Rule sol87 1987 only - May 29 11:57:15s 0:02:45 -
+Rule sol87 1987 only - May 30 11:57:25s 0:02:35 -
+Rule sol87 1987 only - May 31 11:57:30s 0:02:30 -
+Rule sol87 1987 only - Jun 1 11:57:40s 0:02:20 -
+Rule sol87 1987 only - Jun 2 11:57:50s 0:02:10 -
+Rule sol87 1987 only - Jun 3 11:58:00s 0:02:00 -
+Rule sol87 1987 only - Jun 4 11:58:10s 0:01:50 -
+Rule sol87 1987 only - Jun 5 11:58:20s 0:01:40 -
+Rule sol87 1987 only - Jun 6 11:58:30s 0:01:30 -
+Rule sol87 1987 only - Jun 7 11:58:40s 0:01:20 -
+Rule sol87 1987 only - Jun 8 11:58:50s 0:01:10 -
+Rule sol87 1987 only - Jun 9 11:59:05s 0:00:55 -
+Rule sol87 1987 only - Jun 10 11:59:15s 0:00:45 -
+Rule sol87 1987 only - Jun 11 11:59:30s 0:00:30 -
+Rule sol87 1987 only - Jun 12 11:59:40s 0:00:20 -
+Rule sol87 1987 only - Jun 13 11:59:50s 0:00:10 -
+Rule sol87 1987 only - Jun 14 12:00:05s -0:00:05 -
+Rule sol87 1987 only - Jun 15 12:00:15s -0:00:15 -
+Rule sol87 1987 only - Jun 16 12:00:30s -0:00:30 -
+Rule sol87 1987 only - Jun 17 12:00:45s -0:00:45 -
+Rule sol87 1987 only - Jun 18 12:00:55s -0:00:55 -
+Rule sol87 1987 only - Jun 19 12:01:10s -0:01:10 -
+Rule sol87 1987 only - Jun 20 12:01:20s -0:01:20 -
+Rule sol87 1987 only - Jun 21 12:01:35s -0:01:35 -
+Rule sol87 1987 only - Jun 22 12:01:50s -0:01:50 -
+Rule sol87 1987 only - Jun 23 12:02:00s -0:02:00 -
+Rule sol87 1987 only - Jun 24 12:02:15s -0:02:15 -
+Rule sol87 1987 only - Jun 25 12:02:25s -0:02:25 -
+Rule sol87 1987 only - Jun 26 12:02:40s -0:02:40 -
+Rule sol87 1987 only - Jun 27 12:02:50s -0:02:50 -
+Rule sol87 1987 only - Jun 28 12:03:05s -0:03:05 -
+Rule sol87 1987 only - Jun 29 12:03:15s -0:03:15 -
+Rule sol87 1987 only - Jun 30 12:03:30s -0:03:30 -
+Rule sol87 1987 only - Jul 1 12:03:40s -0:03:40 -
+Rule sol87 1987 only - Jul 2 12:03:50s -0:03:50 -
+Rule sol87 1987 only - Jul 3 12:04:05s -0:04:05 -
+Rule sol87 1987 only - Jul 4 12:04:15s -0:04:15 -
+Rule sol87 1987 only - Jul 5 12:04:25s -0:04:25 -
+Rule sol87 1987 only - Jul 6 12:04:35s -0:04:35 -
+Rule sol87 1987 only - Jul 7 12:04:45s -0:04:45 -
+Rule sol87 1987 only - Jul 8 12:04:55s -0:04:55 -
+Rule sol87 1987 only - Jul 9 12:05:05s -0:05:05 -
+Rule sol87 1987 only - Jul 10 12:05:15s -0:05:15 -
+Rule sol87 1987 only - Jul 11 12:05:20s -0:05:20 -
+Rule sol87 1987 only - Jul 12 12:05:30s -0:05:30 -
+Rule sol87 1987 only - Jul 13 12:05:40s -0:05:40 -
+Rule sol87 1987 only - Jul 14 12:05:45s -0:05:45 -
+Rule sol87 1987 only - Jul 15 12:05:50s -0:05:50 -
+Rule sol87 1987 only - Jul 16 12:06:00s -0:06:00 -
+Rule sol87 1987 only - Jul 17 12:06:05s -0:06:05 -
+Rule sol87 1987 only - Jul 18 12:06:10s -0:06:10 -
+Rule sol87 1987 only - Jul 19 12:06:15s -0:06:15 -
+Rule sol87 1987 only - Jul 20 12:06:15s -0:06:15 -
+Rule sol87 1987 only - Jul 21 12:06:20s -0:06:20 -
+Rule sol87 1987 only - Jul 22 12:06:25s -0:06:25 -
+Rule sol87 1987 only - Jul 23 12:06:25s -0:06:25 -
+Rule sol87 1987 only - Jul 24 12:06:25s -0:06:25 -
+Rule sol87 1987 only - Jul 25 12:06:30s -0:06:30 -
+Rule sol87 1987 only - Jul 26 12:06:30s -0:06:30 -
+Rule sol87 1987 only - Jul 27 12:06:30s -0:06:30 -
+Rule sol87 1987 only - Jul 28 12:06:30s -0:06:30 -
+Rule sol87 1987 only - Jul 29 12:06:25s -0:06:25 -
+Rule sol87 1987 only - Jul 30 12:06:25s -0:06:25 -
+Rule sol87 1987 only - Jul 31 12:06:25s -0:06:25 -
+Rule sol87 1987 only - Aug 1 12:06:20s -0:06:20 -
+Rule sol87 1987 only - Aug 2 12:06:15s -0:06:15 -
+Rule sol87 1987 only - Aug 3 12:06:10s -0:06:10 -
+Rule sol87 1987 only - Aug 4 12:06:05s -0:06:05 -
+Rule sol87 1987 only - Aug 5 12:06:00s -0:06:00 -
+Rule sol87 1987 only - Aug 6 12:05:55s -0:05:55 -
+Rule sol87 1987 only - Aug 7 12:05:50s -0:05:50 -
+Rule sol87 1987 only - Aug 8 12:05:40s -0:05:40 -
+Rule sol87 1987 only - Aug 9 12:05:35s -0:05:35 -
+Rule sol87 1987 only - Aug 10 12:05:25s -0:05:25 -
+Rule sol87 1987 only - Aug 11 12:05:15s -0:05:15 -
+Rule sol87 1987 only - Aug 12 12:05:05s -0:05:05 -
+Rule sol87 1987 only - Aug 13 12:04:55s -0:04:55 -
+Rule sol87 1987 only - Aug 14 12:04:45s -0:04:45 -
+Rule sol87 1987 only - Aug 15 12:04:35s -0:04:35 -
+Rule sol87 1987 only - Aug 16 12:04:25s -0:04:25 -
+Rule sol87 1987 only - Aug 17 12:04:10s -0:04:10 -
+Rule sol87 1987 only - Aug 18 12:04:00s -0:04:00 -
+Rule sol87 1987 only - Aug 19 12:03:45s -0:03:45 -
+Rule sol87 1987 only - Aug 20 12:03:30s -0:03:30 -
+Rule sol87 1987 only - Aug 21 12:03:15s -0:03:15 -
+Rule sol87 1987 only - Aug 22 12:03:00s -0:03:00 -
+Rule sol87 1987 only - Aug 23 12:02:45s -0:02:45 -
+Rule sol87 1987 only - Aug 24 12:02:30s -0:02:30 -
+Rule sol87 1987 only - Aug 25 12:02:15s -0:02:15 -
+Rule sol87 1987 only - Aug 26 12:02:00s -0:02:00 -
+Rule sol87 1987 only - Aug 27 12:01:40s -0:01:40 -
+Rule sol87 1987 only - Aug 28 12:01:25s -0:01:25 -
+Rule sol87 1987 only - Aug 29 12:01:05s -0:01:05 -
+Rule sol87 1987 only - Aug 30 12:00:50s -0:00:50 -
+Rule sol87 1987 only - Aug 31 12:00:30s -0:00:30 -
+Rule sol87 1987 only - Sep 1 12:00:10s -0:00:10 -
+Rule sol87 1987 only - Sep 2 11:59:50s 0:00:10 -
+Rule sol87 1987 only - Sep 3 11:59:35s 0:00:25 -
+Rule sol87 1987 only - Sep 4 11:59:15s 0:00:45 -
+Rule sol87 1987 only - Sep 5 11:58:55s 0:01:05 -
+Rule sol87 1987 only - Sep 6 11:58:35s 0:01:25 -
+Rule sol87 1987 only - Sep 7 11:58:15s 0:01:45 -
+Rule sol87 1987 only - Sep 8 11:57:55s 0:02:05 -
+Rule sol87 1987 only - Sep 9 11:57:30s 0:02:30 -
+Rule sol87 1987 only - Sep 10 11:57:10s 0:02:50 -
+Rule sol87 1987 only - Sep 11 11:56:50s 0:03:10 -
+Rule sol87 1987 only - Sep 12 11:56:30s 0:03:30 -
+Rule sol87 1987 only - Sep 13 11:56:10s 0:03:50 -
+Rule sol87 1987 only - Sep 14 11:55:45s 0:04:15 -
+Rule sol87 1987 only - Sep 15 11:55:25s 0:04:35 -
+Rule sol87 1987 only - Sep 16 11:55:05s 0:04:55 -
+Rule sol87 1987 only - Sep 17 11:54:45s 0:05:15 -
+Rule sol87 1987 only - Sep 18 11:54:20s 0:05:40 -
+Rule sol87 1987 only - Sep 19 11:54:00s 0:06:00 -
+Rule sol87 1987 only - Sep 20 11:53:40s 0:06:20 -
+Rule sol87 1987 only - Sep 21 11:53:15s 0:06:45 -
+Rule sol87 1987 only - Sep 22 11:52:55s 0:07:05 -
+Rule sol87 1987 only - Sep 23 11:52:35s 0:07:25 -
+Rule sol87 1987 only - Sep 24 11:52:15s 0:07:45 -
+Rule sol87 1987 only - Sep 25 11:51:55s 0:08:05 -
+Rule sol87 1987 only - Sep 26 11:51:35s 0:08:25 -
+Rule sol87 1987 only - Sep 27 11:51:10s 0:08:50 -
+Rule sol87 1987 only - Sep 28 11:50:50s 0:09:10 -
+Rule sol87 1987 only - Sep 29 11:50:30s 0:09:30 -
+Rule sol87 1987 only - Sep 30 11:50:10s 0:09:50 -
+Rule sol87 1987 only - Oct 1 11:49:50s 0:10:10 -
+Rule sol87 1987 only - Oct 2 11:49:35s 0:10:25 -
+Rule sol87 1987 only - Oct 3 11:49:15s 0:10:45 -
+Rule sol87 1987 only - Oct 4 11:48:55s 0:11:05 -
+Rule sol87 1987 only - Oct 5 11:48:35s 0:11:25 -
+Rule sol87 1987 only - Oct 6 11:48:20s 0:11:40 -
+Rule sol87 1987 only - Oct 7 11:48:00s 0:12:00 -
+Rule sol87 1987 only - Oct 8 11:47:45s 0:12:15 -
+Rule sol87 1987 only - Oct 9 11:47:25s 0:12:35 -
+Rule sol87 1987 only - Oct 10 11:47:10s 0:12:50 -
+Rule sol87 1987 only - Oct 11 11:46:55s 0:13:05 -
+Rule sol87 1987 only - Oct 12 11:46:40s 0:13:20 -
+Rule sol87 1987 only - Oct 13 11:46:25s 0:13:35 -
+Rule sol87 1987 only - Oct 14 11:46:10s 0:13:50 -
+Rule sol87 1987 only - Oct 15 11:45:55s 0:14:05 -
+Rule sol87 1987 only - Oct 16 11:45:45s 0:14:15 -
+Rule sol87 1987 only - Oct 17 11:45:30s 0:14:30 -
+Rule sol87 1987 only - Oct 18 11:45:20s 0:14:40 -
+Rule sol87 1987 only - Oct 19 11:45:05s 0:14:55 -
+Rule sol87 1987 only - Oct 20 11:44:55s 0:15:05 -
+Rule sol87 1987 only - Oct 21 11:44:45s 0:15:15 -
+Rule sol87 1987 only - Oct 22 11:44:35s 0:15:25 -
+Rule sol87 1987 only - Oct 23 11:44:25s 0:15:35 -
+Rule sol87 1987 only - Oct 24 11:44:20s 0:15:40 -
+Rule sol87 1987 only - Oct 25 11:44:10s 0:15:50 -
+Rule sol87 1987 only - Oct 26 11:44:05s 0:15:55 -
+Rule sol87 1987 only - Oct 27 11:43:55s 0:16:05 -
+Rule sol87 1987 only - Oct 28 11:43:50s 0:16:10 -
+Rule sol87 1987 only - Oct 29 11:43:45s 0:16:15 -
+Rule sol87 1987 only - Oct 30 11:43:45s 0:16:15 -
+Rule sol87 1987 only - Oct 31 11:43:40s 0:16:20 -
+Rule sol87 1987 only - Nov 1 11:43:40s 0:16:20 -
+Rule sol87 1987 only - Nov 2 11:43:35s 0:16:25 -
+Rule sol87 1987 only - Nov 3 11:43:35s 0:16:25 -
+Rule sol87 1987 only - Nov 4 11:43:35s 0:16:25 -
+Rule sol87 1987 only - Nov 5 11:43:35s 0:16:25 -
+Rule sol87 1987 only - Nov 6 11:43:40s 0:16:20 -
+Rule sol87 1987 only - Nov 7 11:43:40s 0:16:20 -
+Rule sol87 1987 only - Nov 8 11:43:45s 0:16:15 -
+Rule sol87 1987 only - Nov 9 11:43:50s 0:16:10 -
+Rule sol87 1987 only - Nov 10 11:43:55s 0:16:05 -
+Rule sol87 1987 only - Nov 11 11:44:00s 0:16:00 -
+Rule sol87 1987 only - Nov 12 11:44:05s 0:15:55 -
+Rule sol87 1987 only - Nov 13 11:44:15s 0:15:45 -
+Rule sol87 1987 only - Nov 14 11:44:20s 0:15:40 -
+Rule sol87 1987 only - Nov 15 11:44:30s 0:15:30 -
+Rule sol87 1987 only - Nov 16 11:44:40s 0:15:20 -
+Rule sol87 1987 only - Nov 17 11:44:50s 0:15:10 -
+Rule sol87 1987 only - Nov 18 11:45:05s 0:14:55 -
+Rule sol87 1987 only - Nov 19 11:45:15s 0:14:45 -
+Rule sol87 1987 only - Nov 20 11:45:30s 0:14:30 -
+Rule sol87 1987 only - Nov 21 11:45:45s 0:14:15 -
+Rule sol87 1987 only - Nov 22 11:46:00s 0:14:00 -
+Rule sol87 1987 only - Nov 23 11:46:15s 0:13:45 -
+Rule sol87 1987 only - Nov 24 11:46:30s 0:13:30 -
+Rule sol87 1987 only - Nov 25 11:46:50s 0:13:10 -
+Rule sol87 1987 only - Nov 26 11:47:10s 0:12:50 -
+Rule sol87 1987 only - Nov 27 11:47:25s 0:12:35 -
+Rule sol87 1987 only - Nov 28 11:47:45s 0:12:15 -
+Rule sol87 1987 only - Nov 29 11:48:05s 0:11:55 -
+Rule sol87 1987 only - Nov 30 11:48:30s 0:11:30 -
+Rule sol87 1987 only - Dec 1 11:48:50s 0:11:10 -
+Rule sol87 1987 only - Dec 2 11:49:10s 0:10:50 -
+Rule sol87 1987 only - Dec 3 11:49:35s 0:10:25 -
+Rule sol87 1987 only - Dec 4 11:50:00s 0:10:00 -
+Rule sol87 1987 only - Dec 5 11:50:25s 0:09:35 -
+Rule sol87 1987 only - Dec 6 11:50:50s 0:09:10 -
+Rule sol87 1987 only - Dec 7 11:51:15s 0:08:45 -
+Rule sol87 1987 only - Dec 8 11:51:40s 0:08:20 -
+Rule sol87 1987 only - Dec 9 11:52:05s 0:07:55 -
+Rule sol87 1987 only - Dec 10 11:52:30s 0:07:30 -
+Rule sol87 1987 only - Dec 11 11:53:00s 0:07:00 -
+Rule sol87 1987 only - Dec 12 11:53:25s 0:06:35 -
+Rule sol87 1987 only - Dec 13 11:53:55s 0:06:05 -
+Rule sol87 1987 only - Dec 14 11:54:25s 0:05:35 -
+Rule sol87 1987 only - Dec 15 11:54:50s 0:05:10 -
+Rule sol87 1987 only - Dec 16 11:55:20s 0:04:40 -
+Rule sol87 1987 only - Dec 17 11:55:50s 0:04:10 -
+Rule sol87 1987 only - Dec 18 11:56:20s 0:03:40 -
+Rule sol87 1987 only - Dec 19 11:56:50s 0:03:10 -
+Rule sol87 1987 only - Dec 20 11:57:20s 0:02:40 -
+Rule sol87 1987 only - Dec 21 11:57:50s 0:02:10 -
+Rule sol87 1987 only - Dec 22 11:58:20s 0:01:40 -
+Rule sol87 1987 only - Dec 23 11:58:50s 0:01:10 -
+Rule sol87 1987 only - Dec 24 11:59:20s 0:00:40 -
+Rule sol87 1987 only - Dec 25 11:59:50s 0:00:10 -
+Rule sol87 1987 only - Dec 26 12:00:20s -0:00:20 -
+Rule sol87 1987 only - Dec 27 12:00:45s -0:00:45 -
+Rule sol87 1987 only - Dec 28 12:01:15s -0:01:15 -
+Rule sol87 1987 only - Dec 29 12:01:45s -0:01:45 -
+Rule sol87 1987 only - Dec 30 12:02:15s -0:02:15 -
+Rule sol87 1987 only - Dec 31 12:02:45s -0:02:45 -
+
+# Riyadh is at about 46 degrees 46 minutes East: 3 hrs, 7 mins, 4 secs
+# Before and after 1987, we'll operate on local mean solar time.
+
+# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL]
+Zone Asia/Riyadh87 3:07:04 - zzz 1987
+ 3:07:04 sol87 zzz 1988
+ 3:07:04 - zzz
+# For backward compatibility...
+Link Asia/Riyadh87 Mideast/Riyadh87
diff --git a/tools/zoneinfo/tzdata2008h/solar88 b/tools/zoneinfo/tzdata2008h/solar88
new file mode 100644
index 0000000..b4cfe8e
--- /dev/null
+++ b/tools/zoneinfo/tzdata2008h/solar88
@@ -0,0 +1,388 @@
+# @(#)solar88 8.1
+
+# Apparent noon times below are for Riyadh; they're a bit off for other places.
+# Times were computed using formulas in the U.S. Naval Observatory's
+# Almanac for Computers 1988; the formulas "will give EqT to an accuracy of
+# [plus or minus two] seconds during the current year."
+#
+# Rounding to the nearest five seconds results in fewer than
+# 256 different "time types"--a limit that's faced because time types are
+# stored on disk as unsigned chars.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule sol88 1988 only - Jan 1 12:03:15s -0:03:15 -
+Rule sol88 1988 only - Jan 2 12:03:40s -0:03:40 -
+Rule sol88 1988 only - Jan 3 12:04:10s -0:04:10 -
+Rule sol88 1988 only - Jan 4 12:04:40s -0:04:40 -
+Rule sol88 1988 only - Jan 5 12:05:05s -0:05:05 -
+Rule sol88 1988 only - Jan 6 12:05:30s -0:05:30 -
+Rule sol88 1988 only - Jan 7 12:06:00s -0:06:00 -
+Rule sol88 1988 only - Jan 8 12:06:25s -0:06:25 -
+Rule sol88 1988 only - Jan 9 12:06:50s -0:06:50 -
+Rule sol88 1988 only - Jan 10 12:07:15s -0:07:15 -
+Rule sol88 1988 only - Jan 11 12:07:40s -0:07:40 -
+Rule sol88 1988 only - Jan 12 12:08:05s -0:08:05 -
+Rule sol88 1988 only - Jan 13 12:08:25s -0:08:25 -
+Rule sol88 1988 only - Jan 14 12:08:50s -0:08:50 -
+Rule sol88 1988 only - Jan 15 12:09:10s -0:09:10 -
+Rule sol88 1988 only - Jan 16 12:09:30s -0:09:30 -
+Rule sol88 1988 only - Jan 17 12:09:50s -0:09:50 -
+Rule sol88 1988 only - Jan 18 12:10:10s -0:10:10 -
+Rule sol88 1988 only - Jan 19 12:10:30s -0:10:30 -
+Rule sol88 1988 only - Jan 20 12:10:50s -0:10:50 -
+Rule sol88 1988 only - Jan 21 12:11:05s -0:11:05 -
+Rule sol88 1988 only - Jan 22 12:11:25s -0:11:25 -
+Rule sol88 1988 only - Jan 23 12:11:40s -0:11:40 -
+Rule sol88 1988 only - Jan 24 12:11:55s -0:11:55 -
+Rule sol88 1988 only - Jan 25 12:12:10s -0:12:10 -
+Rule sol88 1988 only - Jan 26 12:12:25s -0:12:25 -
+Rule sol88 1988 only - Jan 27 12:12:40s -0:12:40 -
+Rule sol88 1988 only - Jan 28 12:12:50s -0:12:50 -
+Rule sol88 1988 only - Jan 29 12:13:00s -0:13:00 -
+Rule sol88 1988 only - Jan 30 12:13:10s -0:13:10 -
+Rule sol88 1988 only - Jan 31 12:13:20s -0:13:20 -
+Rule sol88 1988 only - Feb 1 12:13:30s -0:13:30 -
+Rule sol88 1988 only - Feb 2 12:13:40s -0:13:40 -
+Rule sol88 1988 only - Feb 3 12:13:45s -0:13:45 -
+Rule sol88 1988 only - Feb 4 12:13:55s -0:13:55 -
+Rule sol88 1988 only - Feb 5 12:14:00s -0:14:00 -
+Rule sol88 1988 only - Feb 6 12:14:05s -0:14:05 -
+Rule sol88 1988 only - Feb 7 12:14:10s -0:14:10 -
+Rule sol88 1988 only - Feb 8 12:14:10s -0:14:10 -
+Rule sol88 1988 only - Feb 9 12:14:15s -0:14:15 -
+Rule sol88 1988 only - Feb 10 12:14:15s -0:14:15 -
+Rule sol88 1988 only - Feb 11 12:14:15s -0:14:15 -
+Rule sol88 1988 only - Feb 12 12:14:15s -0:14:15 -
+Rule sol88 1988 only - Feb 13 12:14:15s -0:14:15 -
+Rule sol88 1988 only - Feb 14 12:14:15s -0:14:15 -
+Rule sol88 1988 only - Feb 15 12:14:10s -0:14:10 -
+Rule sol88 1988 only - Feb 16 12:14:10s -0:14:10 -
+Rule sol88 1988 only - Feb 17 12:14:05s -0:14:05 -
+Rule sol88 1988 only - Feb 18 12:14:00s -0:14:00 -
+Rule sol88 1988 only - Feb 19 12:13:55s -0:13:55 -
+Rule sol88 1988 only - Feb 20 12:13:50s -0:13:50 -
+Rule sol88 1988 only - Feb 21 12:13:45s -0:13:45 -
+Rule sol88 1988 only - Feb 22 12:13:40s -0:13:40 -
+Rule sol88 1988 only - Feb 23 12:13:30s -0:13:30 -
+Rule sol88 1988 only - Feb 24 12:13:20s -0:13:20 -
+Rule sol88 1988 only - Feb 25 12:13:15s -0:13:15 -
+Rule sol88 1988 only - Feb 26 12:13:05s -0:13:05 -
+Rule sol88 1988 only - Feb 27 12:12:55s -0:12:55 -
+Rule sol88 1988 only - Feb 28 12:12:45s -0:12:45 -
+Rule sol88 1988 only - Feb 29 12:12:30s -0:12:30 -
+Rule sol88 1988 only - Mar 1 12:12:20s -0:12:20 -
+Rule sol88 1988 only - Mar 2 12:12:10s -0:12:10 -
+Rule sol88 1988 only - Mar 3 12:11:55s -0:11:55 -
+Rule sol88 1988 only - Mar 4 12:11:45s -0:11:45 -
+Rule sol88 1988 only - Mar 5 12:11:30s -0:11:30 -
+Rule sol88 1988 only - Mar 6 12:11:15s -0:11:15 -
+Rule sol88 1988 only - Mar 7 12:11:00s -0:11:00 -
+Rule sol88 1988 only - Mar 8 12:10:45s -0:10:45 -
+Rule sol88 1988 only - Mar 9 12:10:30s -0:10:30 -
+Rule sol88 1988 only - Mar 10 12:10:15s -0:10:15 -
+Rule sol88 1988 only - Mar 11 12:10:00s -0:10:00 -
+Rule sol88 1988 only - Mar 12 12:09:45s -0:09:45 -
+Rule sol88 1988 only - Mar 13 12:09:30s -0:09:30 -
+Rule sol88 1988 only - Mar 14 12:09:10s -0:09:10 -
+Rule sol88 1988 only - Mar 15 12:08:55s -0:08:55 -
+Rule sol88 1988 only - Mar 16 12:08:40s -0:08:40 -
+Rule sol88 1988 only - Mar 17 12:08:20s -0:08:20 -
+Rule sol88 1988 only - Mar 18 12:08:05s -0:08:05 -
+Rule sol88 1988 only - Mar 19 12:07:45s -0:07:45 -
+Rule sol88 1988 only - Mar 20 12:07:30s -0:07:30 -
+Rule sol88 1988 only - Mar 21 12:07:10s -0:07:10 -
+Rule sol88 1988 only - Mar 22 12:06:50s -0:06:50 -
+Rule sol88 1988 only - Mar 23 12:06:35s -0:06:35 -
+Rule sol88 1988 only - Mar 24 12:06:15s -0:06:15 -
+Rule sol88 1988 only - Mar 25 12:06:00s -0:06:00 -
+Rule sol88 1988 only - Mar 26 12:05:40s -0:05:40 -
+Rule sol88 1988 only - Mar 27 12:05:20s -0:05:20 -
+Rule sol88 1988 only - Mar 28 12:05:05s -0:05:05 -
+Rule sol88 1988 only - Mar 29 12:04:45s -0:04:45 -
+Rule sol88 1988 only - Mar 30 12:04:25s -0:04:25 -
+Rule sol88 1988 only - Mar 31 12:04:10s -0:04:10 -
+Rule sol88 1988 only - Apr 1 12:03:50s -0:03:50 -
+Rule sol88 1988 only - Apr 2 12:03:35s -0:03:35 -
+Rule sol88 1988 only - Apr 3 12:03:15s -0:03:15 -
+Rule sol88 1988 only - Apr 4 12:03:00s -0:03:00 -
+Rule sol88 1988 only - Apr 5 12:02:40s -0:02:40 -
+Rule sol88 1988 only - Apr 6 12:02:25s -0:02:25 -
+Rule sol88 1988 only - Apr 7 12:02:05s -0:02:05 -
+Rule sol88 1988 only - Apr 8 12:01:50s -0:01:50 -
+Rule sol88 1988 only - Apr 9 12:01:35s -0:01:35 -
+Rule sol88 1988 only - Apr 10 12:01:15s -0:01:15 -
+Rule sol88 1988 only - Apr 11 12:01:00s -0:01:00 -
+Rule sol88 1988 only - Apr 12 12:00:45s -0:00:45 -
+Rule sol88 1988 only - Apr 13 12:00:30s -0:00:30 -
+Rule sol88 1988 only - Apr 14 12:00:15s -0:00:15 -
+Rule sol88 1988 only - Apr 15 12:00:00s 0:00:00 -
+Rule sol88 1988 only - Apr 16 11:59:45s 0:00:15 -
+Rule sol88 1988 only - Apr 17 11:59:30s 0:00:30 -
+Rule sol88 1988 only - Apr 18 11:59:20s 0:00:40 -
+Rule sol88 1988 only - Apr 19 11:59:05s 0:00:55 -
+Rule sol88 1988 only - Apr 20 11:58:55s 0:01:05 -
+Rule sol88 1988 only - Apr 21 11:58:40s 0:01:20 -
+Rule sol88 1988 only - Apr 22 11:58:30s 0:01:30 -
+Rule sol88 1988 only - Apr 23 11:58:15s 0:01:45 -
+Rule sol88 1988 only - Apr 24 11:58:05s 0:01:55 -
+Rule sol88 1988 only - Apr 25 11:57:55s 0:02:05 -
+Rule sol88 1988 only - Apr 26 11:57:45s 0:02:15 -
+Rule sol88 1988 only - Apr 27 11:57:35s 0:02:25 -
+Rule sol88 1988 only - Apr 28 11:57:30s 0:02:30 -
+Rule sol88 1988 only - Apr 29 11:57:20s 0:02:40 -
+Rule sol88 1988 only - Apr 30 11:57:10s 0:02:50 -
+Rule sol88 1988 only - May 1 11:57:05s 0:02:55 -
+Rule sol88 1988 only - May 2 11:56:55s 0:03:05 -
+Rule sol88 1988 only - May 3 11:56:50s 0:03:10 -
+Rule sol88 1988 only - May 4 11:56:45s 0:03:15 -
+Rule sol88 1988 only - May 5 11:56:40s 0:03:20 -
+Rule sol88 1988 only - May 6 11:56:35s 0:03:25 -
+Rule sol88 1988 only - May 7 11:56:30s 0:03:30 -
+Rule sol88 1988 only - May 8 11:56:25s 0:03:35 -
+Rule sol88 1988 only - May 9 11:56:25s 0:03:35 -
+Rule sol88 1988 only - May 10 11:56:20s 0:03:40 -
+Rule sol88 1988 only - May 11 11:56:20s 0:03:40 -
+Rule sol88 1988 only - May 12 11:56:20s 0:03:40 -
+Rule sol88 1988 only - May 13 11:56:20s 0:03:40 -
+Rule sol88 1988 only - May 14 11:56:20s 0:03:40 -
+Rule sol88 1988 only - May 15 11:56:20s 0:03:40 -
+Rule sol88 1988 only - May 16 11:56:20s 0:03:40 -
+Rule sol88 1988 only - May 17 11:56:20s 0:03:40 -
+Rule sol88 1988 only - May 18 11:56:25s 0:03:35 -
+Rule sol88 1988 only - May 19 11:56:25s 0:03:35 -
+Rule sol88 1988 only - May 20 11:56:30s 0:03:30 -
+Rule sol88 1988 only - May 21 11:56:35s 0:03:25 -
+Rule sol88 1988 only - May 22 11:56:40s 0:03:20 -
+Rule sol88 1988 only - May 23 11:56:45s 0:03:15 -
+Rule sol88 1988 only - May 24 11:56:50s 0:03:10 -
+Rule sol88 1988 only - May 25 11:56:55s 0:03:05 -
+Rule sol88 1988 only - May 26 11:57:00s 0:03:00 -
+Rule sol88 1988 only - May 27 11:57:05s 0:02:55 -
+Rule sol88 1988 only - May 28 11:57:15s 0:02:45 -
+Rule sol88 1988 only - May 29 11:57:20s 0:02:40 -
+Rule sol88 1988 only - May 30 11:57:30s 0:02:30 -
+Rule sol88 1988 only - May 31 11:57:40s 0:02:20 -
+Rule sol88 1988 only - Jun 1 11:57:50s 0:02:10 -
+Rule sol88 1988 only - Jun 2 11:57:55s 0:02:05 -
+Rule sol88 1988 only - Jun 3 11:58:05s 0:01:55 -
+Rule sol88 1988 only - Jun 4 11:58:15s 0:01:45 -
+Rule sol88 1988 only - Jun 5 11:58:30s 0:01:30 -
+Rule sol88 1988 only - Jun 6 11:58:40s 0:01:20 -
+Rule sol88 1988 only - Jun 7 11:58:50s 0:01:10 -
+Rule sol88 1988 only - Jun 8 11:59:00s 0:01:00 -
+Rule sol88 1988 only - Jun 9 11:59:15s 0:00:45 -
+Rule sol88 1988 only - Jun 10 11:59:25s 0:00:35 -
+Rule sol88 1988 only - Jun 11 11:59:35s 0:00:25 -
+Rule sol88 1988 only - Jun 12 11:59:50s 0:00:10 -
+Rule sol88 1988 only - Jun 13 12:00:00s 0:00:00 -
+Rule sol88 1988 only - Jun 14 12:00:15s -0:00:15 -
+Rule sol88 1988 only - Jun 15 12:00:25s -0:00:25 -
+Rule sol88 1988 only - Jun 16 12:00:40s -0:00:40 -
+Rule sol88 1988 only - Jun 17 12:00:55s -0:00:55 -
+Rule sol88 1988 only - Jun 18 12:01:05s -0:01:05 -
+Rule sol88 1988 only - Jun 19 12:01:20s -0:01:20 -
+Rule sol88 1988 only - Jun 20 12:01:30s -0:01:30 -
+Rule sol88 1988 only - Jun 21 12:01:45s -0:01:45 -
+Rule sol88 1988 only - Jun 22 12:02:00s -0:02:00 -
+Rule sol88 1988 only - Jun 23 12:02:10s -0:02:10 -
+Rule sol88 1988 only - Jun 24 12:02:25s -0:02:25 -
+Rule sol88 1988 only - Jun 25 12:02:35s -0:02:35 -
+Rule sol88 1988 only - Jun 26 12:02:50s -0:02:50 -
+Rule sol88 1988 only - Jun 27 12:03:00s -0:03:00 -
+Rule sol88 1988 only - Jun 28 12:03:15s -0:03:15 -
+Rule sol88 1988 only - Jun 29 12:03:25s -0:03:25 -
+Rule sol88 1988 only - Jun 30 12:03:40s -0:03:40 -
+Rule sol88 1988 only - Jul 1 12:03:50s -0:03:50 -
+Rule sol88 1988 only - Jul 2 12:04:00s -0:04:00 -
+Rule sol88 1988 only - Jul 3 12:04:10s -0:04:10 -
+Rule sol88 1988 only - Jul 4 12:04:25s -0:04:25 -
+Rule sol88 1988 only - Jul 5 12:04:35s -0:04:35 -
+Rule sol88 1988 only - Jul 6 12:04:45s -0:04:45 -
+Rule sol88 1988 only - Jul 7 12:04:55s -0:04:55 -
+Rule sol88 1988 only - Jul 8 12:05:05s -0:05:05 -
+Rule sol88 1988 only - Jul 9 12:05:10s -0:05:10 -
+Rule sol88 1988 only - Jul 10 12:05:20s -0:05:20 -
+Rule sol88 1988 only - Jul 11 12:05:30s -0:05:30 -
+Rule sol88 1988 only - Jul 12 12:05:35s -0:05:35 -
+Rule sol88 1988 only - Jul 13 12:05:45s -0:05:45 -
+Rule sol88 1988 only - Jul 14 12:05:50s -0:05:50 -
+Rule sol88 1988 only - Jul 15 12:05:55s -0:05:55 -
+Rule sol88 1988 only - Jul 16 12:06:00s -0:06:00 -
+Rule sol88 1988 only - Jul 17 12:06:05s -0:06:05 -
+Rule sol88 1988 only - Jul 18 12:06:10s -0:06:10 -
+Rule sol88 1988 only - Jul 19 12:06:15s -0:06:15 -
+Rule sol88 1988 only - Jul 20 12:06:20s -0:06:20 -
+Rule sol88 1988 only - Jul 21 12:06:25s -0:06:25 -
+Rule sol88 1988 only - Jul 22 12:06:25s -0:06:25 -
+Rule sol88 1988 only - Jul 23 12:06:25s -0:06:25 -
+Rule sol88 1988 only - Jul 24 12:06:30s -0:06:30 -
+Rule sol88 1988 only - Jul 25 12:06:30s -0:06:30 -
+Rule sol88 1988 only - Jul 26 12:06:30s -0:06:30 -
+Rule sol88 1988 only - Jul 27 12:06:30s -0:06:30 -
+Rule sol88 1988 only - Jul 28 12:06:30s -0:06:30 -
+Rule sol88 1988 only - Jul 29 12:06:25s -0:06:25 -
+Rule sol88 1988 only - Jul 30 12:06:25s -0:06:25 -
+Rule sol88 1988 only - Jul 31 12:06:20s -0:06:20 -
+Rule sol88 1988 only - Aug 1 12:06:15s -0:06:15 -
+Rule sol88 1988 only - Aug 2 12:06:15s -0:06:15 -
+Rule sol88 1988 only - Aug 3 12:06:10s -0:06:10 -
+Rule sol88 1988 only - Aug 4 12:06:05s -0:06:05 -
+Rule sol88 1988 only - Aug 5 12:05:55s -0:05:55 -
+Rule sol88 1988 only - Aug 6 12:05:50s -0:05:50 -
+Rule sol88 1988 only - Aug 7 12:05:45s -0:05:45 -
+Rule sol88 1988 only - Aug 8 12:05:35s -0:05:35 -
+Rule sol88 1988 only - Aug 9 12:05:25s -0:05:25 -
+Rule sol88 1988 only - Aug 10 12:05:20s -0:05:20 -
+Rule sol88 1988 only - Aug 11 12:05:10s -0:05:10 -
+Rule sol88 1988 only - Aug 12 12:05:00s -0:05:00 -
+Rule sol88 1988 only - Aug 13 12:04:50s -0:04:50 -
+Rule sol88 1988 only - Aug 14 12:04:35s -0:04:35 -
+Rule sol88 1988 only - Aug 15 12:04:25s -0:04:25 -
+Rule sol88 1988 only - Aug 16 12:04:15s -0:04:15 -
+Rule sol88 1988 only - Aug 17 12:04:00s -0:04:00 -
+Rule sol88 1988 only - Aug 18 12:03:50s -0:03:50 -
+Rule sol88 1988 only - Aug 19 12:03:35s -0:03:35 -
+Rule sol88 1988 only - Aug 20 12:03:20s -0:03:20 -
+Rule sol88 1988 only - Aug 21 12:03:05s -0:03:05 -
+Rule sol88 1988 only - Aug 22 12:02:50s -0:02:50 -
+Rule sol88 1988 only - Aug 23 12:02:35s -0:02:35 -
+Rule sol88 1988 only - Aug 24 12:02:20s -0:02:20 -
+Rule sol88 1988 only - Aug 25 12:02:00s -0:02:00 -
+Rule sol88 1988 only - Aug 26 12:01:45s -0:01:45 -
+Rule sol88 1988 only - Aug 27 12:01:30s -0:01:30 -
+Rule sol88 1988 only - Aug 28 12:01:10s -0:01:10 -
+Rule sol88 1988 only - Aug 29 12:00:50s -0:00:50 -
+Rule sol88 1988 only - Aug 30 12:00:35s -0:00:35 -
+Rule sol88 1988 only - Aug 31 12:00:15s -0:00:15 -
+Rule sol88 1988 only - Sep 1 11:59:55s 0:00:05 -
+Rule sol88 1988 only - Sep 2 11:59:35s 0:00:25 -
+Rule sol88 1988 only - Sep 3 11:59:20s 0:00:40 -
+Rule sol88 1988 only - Sep 4 11:59:00s 0:01:00 -
+Rule sol88 1988 only - Sep 5 11:58:40s 0:01:20 -
+Rule sol88 1988 only - Sep 6 11:58:20s 0:01:40 -
+Rule sol88 1988 only - Sep 7 11:58:00s 0:02:00 -
+Rule sol88 1988 only - Sep 8 11:57:35s 0:02:25 -
+Rule sol88 1988 only - Sep 9 11:57:15s 0:02:45 -
+Rule sol88 1988 only - Sep 10 11:56:55s 0:03:05 -
+Rule sol88 1988 only - Sep 11 11:56:35s 0:03:25 -
+Rule sol88 1988 only - Sep 12 11:56:15s 0:03:45 -
+Rule sol88 1988 only - Sep 13 11:55:50s 0:04:10 -
+Rule sol88 1988 only - Sep 14 11:55:30s 0:04:30 -
+Rule sol88 1988 only - Sep 15 11:55:10s 0:04:50 -
+Rule sol88 1988 only - Sep 16 11:54:50s 0:05:10 -
+Rule sol88 1988 only - Sep 17 11:54:25s 0:05:35 -
+Rule sol88 1988 only - Sep 18 11:54:05s 0:05:55 -
+Rule sol88 1988 only - Sep 19 11:53:45s 0:06:15 -
+Rule sol88 1988 only - Sep 20 11:53:25s 0:06:35 -
+Rule sol88 1988 only - Sep 21 11:53:00s 0:07:00 -
+Rule sol88 1988 only - Sep 22 11:52:40s 0:07:20 -
+Rule sol88 1988 only - Sep 23 11:52:20s 0:07:40 -
+Rule sol88 1988 only - Sep 24 11:52:00s 0:08:00 -
+Rule sol88 1988 only - Sep 25 11:51:40s 0:08:20 -
+Rule sol88 1988 only - Sep 26 11:51:15s 0:08:45 -
+Rule sol88 1988 only - Sep 27 11:50:55s 0:09:05 -
+Rule sol88 1988 only - Sep 28 11:50:35s 0:09:25 -
+Rule sol88 1988 only - Sep 29 11:50:15s 0:09:45 -
+Rule sol88 1988 only - Sep 30 11:49:55s 0:10:05 -
+Rule sol88 1988 only - Oct 1 11:49:35s 0:10:25 -
+Rule sol88 1988 only - Oct 2 11:49:20s 0:10:40 -
+Rule sol88 1988 only - Oct 3 11:49:00s 0:11:00 -
+Rule sol88 1988 only - Oct 4 11:48:40s 0:11:20 -
+Rule sol88 1988 only - Oct 5 11:48:25s 0:11:35 -
+Rule sol88 1988 only - Oct 6 11:48:05s 0:11:55 -
+Rule sol88 1988 only - Oct 7 11:47:50s 0:12:10 -
+Rule sol88 1988 only - Oct 8 11:47:30s 0:12:30 -
+Rule sol88 1988 only - Oct 9 11:47:15s 0:12:45 -
+Rule sol88 1988 only - Oct 10 11:47:00s 0:13:00 -
+Rule sol88 1988 only - Oct 11 11:46:45s 0:13:15 -
+Rule sol88 1988 only - Oct 12 11:46:30s 0:13:30 -
+Rule sol88 1988 only - Oct 13 11:46:15s 0:13:45 -
+Rule sol88 1988 only - Oct 14 11:46:00s 0:14:00 -
+Rule sol88 1988 only - Oct 15 11:45:45s 0:14:15 -
+Rule sol88 1988 only - Oct 16 11:45:35s 0:14:25 -
+Rule sol88 1988 only - Oct 17 11:45:20s 0:14:40 -
+Rule sol88 1988 only - Oct 18 11:45:10s 0:14:50 -
+Rule sol88 1988 only - Oct 19 11:45:00s 0:15:00 -
+Rule sol88 1988 only - Oct 20 11:44:45s 0:15:15 -
+Rule sol88 1988 only - Oct 21 11:44:40s 0:15:20 -
+Rule sol88 1988 only - Oct 22 11:44:30s 0:15:30 -
+Rule sol88 1988 only - Oct 23 11:44:20s 0:15:40 -
+Rule sol88 1988 only - Oct 24 11:44:10s 0:15:50 -
+Rule sol88 1988 only - Oct 25 11:44:05s 0:15:55 -
+Rule sol88 1988 only - Oct 26 11:44:00s 0:16:00 -
+Rule sol88 1988 only - Oct 27 11:43:55s 0:16:05 -
+Rule sol88 1988 only - Oct 28 11:43:50s 0:16:10 -
+Rule sol88 1988 only - Oct 29 11:43:45s 0:16:15 -
+Rule sol88 1988 only - Oct 30 11:43:40s 0:16:20 -
+Rule sol88 1988 only - Oct 31 11:43:40s 0:16:20 -
+Rule sol88 1988 only - Nov 1 11:43:35s 0:16:25 -
+Rule sol88 1988 only - Nov 2 11:43:35s 0:16:25 -
+Rule sol88 1988 only - Nov 3 11:43:35s 0:16:25 -
+Rule sol88 1988 only - Nov 4 11:43:35s 0:16:25 -
+Rule sol88 1988 only - Nov 5 11:43:40s 0:16:20 -
+Rule sol88 1988 only - Nov 6 11:43:40s 0:16:20 -
+Rule sol88 1988 only - Nov 7 11:43:45s 0:16:15 -
+Rule sol88 1988 only - Nov 8 11:43:45s 0:16:15 -
+Rule sol88 1988 only - Nov 9 11:43:50s 0:16:10 -
+Rule sol88 1988 only - Nov 10 11:44:00s 0:16:00 -
+Rule sol88 1988 only - Nov 11 11:44:05s 0:15:55 -
+Rule sol88 1988 only - Nov 12 11:44:10s 0:15:50 -
+Rule sol88 1988 only - Nov 13 11:44:20s 0:15:40 -
+Rule sol88 1988 only - Nov 14 11:44:30s 0:15:30 -
+Rule sol88 1988 only - Nov 15 11:44:40s 0:15:20 -
+Rule sol88 1988 only - Nov 16 11:44:50s 0:15:10 -
+Rule sol88 1988 only - Nov 17 11:45:00s 0:15:00 -
+Rule sol88 1988 only - Nov 18 11:45:15s 0:14:45 -
+Rule sol88 1988 only - Nov 19 11:45:25s 0:14:35 -
+Rule sol88 1988 only - Nov 20 11:45:40s 0:14:20 -
+Rule sol88 1988 only - Nov 21 11:45:55s 0:14:05 -
+Rule sol88 1988 only - Nov 22 11:46:10s 0:13:50 -
+Rule sol88 1988 only - Nov 23 11:46:30s 0:13:30 -
+Rule sol88 1988 only - Nov 24 11:46:45s 0:13:15 -
+Rule sol88 1988 only - Nov 25 11:47:05s 0:12:55 -
+Rule sol88 1988 only - Nov 26 11:47:20s 0:12:40 -
+Rule sol88 1988 only - Nov 27 11:47:40s 0:12:20 -
+Rule sol88 1988 only - Nov 28 11:48:00s 0:12:00 -
+Rule sol88 1988 only - Nov 29 11:48:25s 0:11:35 -
+Rule sol88 1988 only - Nov 30 11:48:45s 0:11:15 -
+Rule sol88 1988 only - Dec 1 11:49:05s 0:10:55 -
+Rule sol88 1988 only - Dec 2 11:49:30s 0:10:30 -
+Rule sol88 1988 only - Dec 3 11:49:55s 0:10:05 -
+Rule sol88 1988 only - Dec 4 11:50:15s 0:09:45 -
+Rule sol88 1988 only - Dec 5 11:50:40s 0:09:20 -
+Rule sol88 1988 only - Dec 6 11:51:05s 0:08:55 -
+Rule sol88 1988 only - Dec 7 11:51:35s 0:08:25 -
+Rule sol88 1988 only - Dec 8 11:52:00s 0:08:00 -
+Rule sol88 1988 only - Dec 9 11:52:25s 0:07:35 -
+Rule sol88 1988 only - Dec 10 11:52:55s 0:07:05 -
+Rule sol88 1988 only - Dec 11 11:53:20s 0:06:40 -
+Rule sol88 1988 only - Dec 12 11:53:50s 0:06:10 -
+Rule sol88 1988 only - Dec 13 11:54:15s 0:05:45 -
+Rule sol88 1988 only - Dec 14 11:54:45s 0:05:15 -
+Rule sol88 1988 only - Dec 15 11:55:15s 0:04:45 -
+Rule sol88 1988 only - Dec 16 11:55:45s 0:04:15 -
+Rule sol88 1988 only - Dec 17 11:56:15s 0:03:45 -
+Rule sol88 1988 only - Dec 18 11:56:40s 0:03:20 -
+Rule sol88 1988 only - Dec 19 11:57:10s 0:02:50 -
+Rule sol88 1988 only - Dec 20 11:57:40s 0:02:20 -
+Rule sol88 1988 only - Dec 21 11:58:10s 0:01:50 -
+Rule sol88 1988 only - Dec 22 11:58:40s 0:01:20 -
+Rule sol88 1988 only - Dec 23 11:59:10s 0:00:50 -
+Rule sol88 1988 only - Dec 24 11:59:40s 0:00:20 -
+Rule sol88 1988 only - Dec 25 12:00:10s -0:00:10 -
+Rule sol88 1988 only - Dec 26 12:00:40s -0:00:40 -
+Rule sol88 1988 only - Dec 27 12:01:10s -0:01:10 -
+Rule sol88 1988 only - Dec 28 12:01:40s -0:01:40 -
+Rule sol88 1988 only - Dec 29 12:02:10s -0:02:10 -
+Rule sol88 1988 only - Dec 30 12:02:35s -0:02:35 -
+Rule sol88 1988 only - Dec 31 12:03:05s -0:03:05 -
+
+# Riyadh is at about 46 degrees 46 minutes East: 3 hrs, 7 mins, 4 secs
+# Before and after 1988, we'll operate on local mean solar time.
+
+# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL]
+Zone Asia/Riyadh88 3:07:04 - zzz 1988
+ 3:07:04 sol88 zzz 1989
+ 3:07:04 - zzz
+# For backward compatibility...
+Link Asia/Riyadh88 Mideast/Riyadh88
diff --git a/tools/zoneinfo/tzdata2008h/solar89 b/tools/zoneinfo/tzdata2008h/solar89
new file mode 100644
index 0000000..8c48531
--- /dev/null
+++ b/tools/zoneinfo/tzdata2008h/solar89
@@ -0,0 +1,393 @@
+# @(#)solar89 8.1
+
+# Apparent noon times below are for Riyadh; they're a bit off for other places.
+# Times were computed using a formula provided by the U. S. Naval Observatory:
+# eqt = -105.8 * sin(l) + 596.2 * sin(2 * l) + 4.4 * sin(3 * l)
+# -12.7 * sin(4 * l) - 429.0 * cos(l) - 2.1 * cos (2 * l)
+# + 19.3 * cos(3 * l);
+# where l is the "mean longitude of the Sun" given by
+# l = 279.642 degrees + 0.985647 * d
+# and d is the interval in days from January 0, 0 hours Universal Time
+# (equaling the day of the year plus the fraction of a day from zero hours).
+# The accuracy of the formula is plus or minus three seconds.
+#
+# Rounding to the nearest five seconds results in fewer than
+# 256 different "time types"--a limit that's faced because time types are
+# stored on disk as unsigned chars.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule sol89 1989 only - Jan 1 12:03:35s -0:03:35 -
+Rule sol89 1989 only - Jan 2 12:04:05s -0:04:05 -
+Rule sol89 1989 only - Jan 3 12:04:30s -0:04:30 -
+Rule sol89 1989 only - Jan 4 12:05:00s -0:05:00 -
+Rule sol89 1989 only - Jan 5 12:05:25s -0:05:25 -
+Rule sol89 1989 only - Jan 6 12:05:50s -0:05:50 -
+Rule sol89 1989 only - Jan 7 12:06:15s -0:06:15 -
+Rule sol89 1989 only - Jan 8 12:06:45s -0:06:45 -
+Rule sol89 1989 only - Jan 9 12:07:10s -0:07:10 -
+Rule sol89 1989 only - Jan 10 12:07:35s -0:07:35 -
+Rule sol89 1989 only - Jan 11 12:07:55s -0:07:55 -
+Rule sol89 1989 only - Jan 12 12:08:20s -0:08:20 -
+Rule sol89 1989 only - Jan 13 12:08:45s -0:08:45 -
+Rule sol89 1989 only - Jan 14 12:09:05s -0:09:05 -
+Rule sol89 1989 only - Jan 15 12:09:25s -0:09:25 -
+Rule sol89 1989 only - Jan 16 12:09:45s -0:09:45 -
+Rule sol89 1989 only - Jan 17 12:10:05s -0:10:05 -
+Rule sol89 1989 only - Jan 18 12:10:25s -0:10:25 -
+Rule sol89 1989 only - Jan 19 12:10:45s -0:10:45 -
+Rule sol89 1989 only - Jan 20 12:11:05s -0:11:05 -
+Rule sol89 1989 only - Jan 21 12:11:20s -0:11:20 -
+Rule sol89 1989 only - Jan 22 12:11:35s -0:11:35 -
+Rule sol89 1989 only - Jan 23 12:11:55s -0:11:55 -
+Rule sol89 1989 only - Jan 24 12:12:10s -0:12:10 -
+Rule sol89 1989 only - Jan 25 12:12:20s -0:12:20 -
+Rule sol89 1989 only - Jan 26 12:12:35s -0:12:35 -
+Rule sol89 1989 only - Jan 27 12:12:50s -0:12:50 -
+Rule sol89 1989 only - Jan 28 12:13:00s -0:13:00 -
+Rule sol89 1989 only - Jan 29 12:13:10s -0:13:10 -
+Rule sol89 1989 only - Jan 30 12:13:20s -0:13:20 -
+Rule sol89 1989 only - Jan 31 12:13:30s -0:13:30 -
+Rule sol89 1989 only - Feb 1 12:13:40s -0:13:40 -
+Rule sol89 1989 only - Feb 2 12:13:45s -0:13:45 -
+Rule sol89 1989 only - Feb 3 12:13:55s -0:13:55 -
+Rule sol89 1989 only - Feb 4 12:14:00s -0:14:00 -
+Rule sol89 1989 only - Feb 5 12:14:05s -0:14:05 -
+Rule sol89 1989 only - Feb 6 12:14:10s -0:14:10 -
+Rule sol89 1989 only - Feb 7 12:14:10s -0:14:10 -
+Rule sol89 1989 only - Feb 8 12:14:15s -0:14:15 -
+Rule sol89 1989 only - Feb 9 12:14:15s -0:14:15 -
+Rule sol89 1989 only - Feb 10 12:14:20s -0:14:20 -
+Rule sol89 1989 only - Feb 11 12:14:20s -0:14:20 -
+Rule sol89 1989 only - Feb 12 12:14:20s -0:14:20 -
+Rule sol89 1989 only - Feb 13 12:14:15s -0:14:15 -
+Rule sol89 1989 only - Feb 14 12:14:15s -0:14:15 -
+Rule sol89 1989 only - Feb 15 12:14:10s -0:14:10 -
+Rule sol89 1989 only - Feb 16 12:14:10s -0:14:10 -
+Rule sol89 1989 only - Feb 17 12:14:05s -0:14:05 -
+Rule sol89 1989 only - Feb 18 12:14:00s -0:14:00 -
+Rule sol89 1989 only - Feb 19 12:13:55s -0:13:55 -
+Rule sol89 1989 only - Feb 20 12:13:50s -0:13:50 -
+Rule sol89 1989 only - Feb 21 12:13:40s -0:13:40 -
+Rule sol89 1989 only - Feb 22 12:13:35s -0:13:35 -
+Rule sol89 1989 only - Feb 23 12:13:25s -0:13:25 -
+Rule sol89 1989 only - Feb 24 12:13:15s -0:13:15 -
+Rule sol89 1989 only - Feb 25 12:13:05s -0:13:05 -
+Rule sol89 1989 only - Feb 26 12:12:55s -0:12:55 -
+Rule sol89 1989 only - Feb 27 12:12:45s -0:12:45 -
+Rule sol89 1989 only - Feb 28 12:12:35s -0:12:35 -
+Rule sol89 1989 only - Mar 1 12:12:25s -0:12:25 -
+Rule sol89 1989 only - Mar 2 12:12:10s -0:12:10 -
+Rule sol89 1989 only - Mar 3 12:12:00s -0:12:00 -
+Rule sol89 1989 only - Mar 4 12:11:45s -0:11:45 -
+Rule sol89 1989 only - Mar 5 12:11:35s -0:11:35 -
+Rule sol89 1989 only - Mar 6 12:11:20s -0:11:20 -
+Rule sol89 1989 only - Mar 7 12:11:05s -0:11:05 -
+Rule sol89 1989 only - Mar 8 12:10:50s -0:10:50 -
+Rule sol89 1989 only - Mar 9 12:10:35s -0:10:35 -
+Rule sol89 1989 only - Mar 10 12:10:20s -0:10:20 -
+Rule sol89 1989 only - Mar 11 12:10:05s -0:10:05 -
+Rule sol89 1989 only - Mar 12 12:09:50s -0:09:50 -
+Rule sol89 1989 only - Mar 13 12:09:30s -0:09:30 -
+Rule sol89 1989 only - Mar 14 12:09:15s -0:09:15 -
+Rule sol89 1989 only - Mar 15 12:09:00s -0:09:00 -
+Rule sol89 1989 only - Mar 16 12:08:40s -0:08:40 -
+Rule sol89 1989 only - Mar 17 12:08:25s -0:08:25 -
+Rule sol89 1989 only - Mar 18 12:08:05s -0:08:05 -
+Rule sol89 1989 only - Mar 19 12:07:50s -0:07:50 -
+Rule sol89 1989 only - Mar 20 12:07:30s -0:07:30 -
+Rule sol89 1989 only - Mar 21 12:07:15s -0:07:15 -
+Rule sol89 1989 only - Mar 22 12:06:55s -0:06:55 -
+Rule sol89 1989 only - Mar 23 12:06:35s -0:06:35 -
+Rule sol89 1989 only - Mar 24 12:06:20s -0:06:20 -
+Rule sol89 1989 only - Mar 25 12:06:00s -0:06:00 -
+Rule sol89 1989 only - Mar 26 12:05:40s -0:05:40 -
+Rule sol89 1989 only - Mar 27 12:05:25s -0:05:25 -
+Rule sol89 1989 only - Mar 28 12:05:05s -0:05:05 -
+Rule sol89 1989 only - Mar 29 12:04:50s -0:04:50 -
+Rule sol89 1989 only - Mar 30 12:04:30s -0:04:30 -
+Rule sol89 1989 only - Mar 31 12:04:10s -0:04:10 -
+Rule sol89 1989 only - Apr 1 12:03:55s -0:03:55 -
+Rule sol89 1989 only - Apr 2 12:03:35s -0:03:35 -
+Rule sol89 1989 only - Apr 3 12:03:20s -0:03:20 -
+Rule sol89 1989 only - Apr 4 12:03:00s -0:03:00 -
+Rule sol89 1989 only - Apr 5 12:02:45s -0:02:45 -
+Rule sol89 1989 only - Apr 6 12:02:25s -0:02:25 -
+Rule sol89 1989 only - Apr 7 12:02:10s -0:02:10 -
+Rule sol89 1989 only - Apr 8 12:01:50s -0:01:50 -
+Rule sol89 1989 only - Apr 9 12:01:35s -0:01:35 -
+Rule sol89 1989 only - Apr 10 12:01:20s -0:01:20 -
+Rule sol89 1989 only - Apr 11 12:01:05s -0:01:05 -
+Rule sol89 1989 only - Apr 12 12:00:50s -0:00:50 -
+Rule sol89 1989 only - Apr 13 12:00:35s -0:00:35 -
+Rule sol89 1989 only - Apr 14 12:00:20s -0:00:20 -
+Rule sol89 1989 only - Apr 15 12:00:05s -0:00:05 -
+Rule sol89 1989 only - Apr 16 11:59:50s 0:00:10 -
+Rule sol89 1989 only - Apr 17 11:59:35s 0:00:25 -
+Rule sol89 1989 only - Apr 18 11:59:20s 0:00:40 -
+Rule sol89 1989 only - Apr 19 11:59:10s 0:00:50 -
+Rule sol89 1989 only - Apr 20 11:58:55s 0:01:05 -
+Rule sol89 1989 only - Apr 21 11:58:45s 0:01:15 -
+Rule sol89 1989 only - Apr 22 11:58:30s 0:01:30 -
+Rule sol89 1989 only - Apr 23 11:58:20s 0:01:40 -
+Rule sol89 1989 only - Apr 24 11:58:10s 0:01:50 -
+Rule sol89 1989 only - Apr 25 11:58:00s 0:02:00 -
+Rule sol89 1989 only - Apr 26 11:57:50s 0:02:10 -
+Rule sol89 1989 only - Apr 27 11:57:40s 0:02:20 -
+Rule sol89 1989 only - Apr 28 11:57:30s 0:02:30 -
+Rule sol89 1989 only - Apr 29 11:57:20s 0:02:40 -
+Rule sol89 1989 only - Apr 30 11:57:15s 0:02:45 -
+Rule sol89 1989 only - May 1 11:57:05s 0:02:55 -
+Rule sol89 1989 only - May 2 11:57:00s 0:03:00 -
+Rule sol89 1989 only - May 3 11:56:50s 0:03:10 -
+Rule sol89 1989 only - May 4 11:56:45s 0:03:15 -
+Rule sol89 1989 only - May 5 11:56:40s 0:03:20 -
+Rule sol89 1989 only - May 6 11:56:35s 0:03:25 -
+Rule sol89 1989 only - May 7 11:56:30s 0:03:30 -
+Rule sol89 1989 only - May 8 11:56:30s 0:03:30 -
+Rule sol89 1989 only - May 9 11:56:25s 0:03:35 -
+Rule sol89 1989 only - May 10 11:56:25s 0:03:35 -
+Rule sol89 1989 only - May 11 11:56:20s 0:03:40 -
+Rule sol89 1989 only - May 12 11:56:20s 0:03:40 -
+Rule sol89 1989 only - May 13 11:56:20s 0:03:40 -
+Rule sol89 1989 only - May 14 11:56:20s 0:03:40 -
+Rule sol89 1989 only - May 15 11:56:20s 0:03:40 -
+Rule sol89 1989 only - May 16 11:56:20s 0:03:40 -
+Rule sol89 1989 only - May 17 11:56:20s 0:03:40 -
+Rule sol89 1989 only - May 18 11:56:25s 0:03:35 -
+Rule sol89 1989 only - May 19 11:56:25s 0:03:35 -
+Rule sol89 1989 only - May 20 11:56:30s 0:03:30 -
+Rule sol89 1989 only - May 21 11:56:35s 0:03:25 -
+Rule sol89 1989 only - May 22 11:56:35s 0:03:25 -
+Rule sol89 1989 only - May 23 11:56:40s 0:03:20 -
+Rule sol89 1989 only - May 24 11:56:45s 0:03:15 -
+Rule sol89 1989 only - May 25 11:56:55s 0:03:05 -
+Rule sol89 1989 only - May 26 11:57:00s 0:03:00 -
+Rule sol89 1989 only - May 27 11:57:05s 0:02:55 -
+Rule sol89 1989 only - May 28 11:57:15s 0:02:45 -
+Rule sol89 1989 only - May 29 11:57:20s 0:02:40 -
+Rule sol89 1989 only - May 30 11:57:30s 0:02:30 -
+Rule sol89 1989 only - May 31 11:57:35s 0:02:25 -
+Rule sol89 1989 only - Jun 1 11:57:45s 0:02:15 -
+Rule sol89 1989 only - Jun 2 11:57:55s 0:02:05 -
+Rule sol89 1989 only - Jun 3 11:58:05s 0:01:55 -
+Rule sol89 1989 only - Jun 4 11:58:15s 0:01:45 -
+Rule sol89 1989 only - Jun 5 11:58:25s 0:01:35 -
+Rule sol89 1989 only - Jun 6 11:58:35s 0:01:25 -
+Rule sol89 1989 only - Jun 7 11:58:45s 0:01:15 -
+Rule sol89 1989 only - Jun 8 11:59:00s 0:01:00 -
+Rule sol89 1989 only - Jun 9 11:59:10s 0:00:50 -
+Rule sol89 1989 only - Jun 10 11:59:20s 0:00:40 -
+Rule sol89 1989 only - Jun 11 11:59:35s 0:00:25 -
+Rule sol89 1989 only - Jun 12 11:59:45s 0:00:15 -
+Rule sol89 1989 only - Jun 13 12:00:00s 0:00:00 -
+Rule sol89 1989 only - Jun 14 12:00:10s -0:00:10 -
+Rule sol89 1989 only - Jun 15 12:00:25s -0:00:25 -
+Rule sol89 1989 only - Jun 16 12:00:35s -0:00:35 -
+Rule sol89 1989 only - Jun 17 12:00:50s -0:00:50 -
+Rule sol89 1989 only - Jun 18 12:01:05s -0:01:05 -
+Rule sol89 1989 only - Jun 19 12:01:15s -0:01:15 -
+Rule sol89 1989 only - Jun 20 12:01:30s -0:01:30 -
+Rule sol89 1989 only - Jun 21 12:01:40s -0:01:40 -
+Rule sol89 1989 only - Jun 22 12:01:55s -0:01:55 -
+Rule sol89 1989 only - Jun 23 12:02:10s -0:02:10 -
+Rule sol89 1989 only - Jun 24 12:02:20s -0:02:20 -
+Rule sol89 1989 only - Jun 25 12:02:35s -0:02:35 -
+Rule sol89 1989 only - Jun 26 12:02:45s -0:02:45 -
+Rule sol89 1989 only - Jun 27 12:03:00s -0:03:00 -
+Rule sol89 1989 only - Jun 28 12:03:10s -0:03:10 -
+Rule sol89 1989 only - Jun 29 12:03:25s -0:03:25 -
+Rule sol89 1989 only - Jun 30 12:03:35s -0:03:35 -
+Rule sol89 1989 only - Jul 1 12:03:45s -0:03:45 -
+Rule sol89 1989 only - Jul 2 12:04:00s -0:04:00 -
+Rule sol89 1989 only - Jul 3 12:04:10s -0:04:10 -
+Rule sol89 1989 only - Jul 4 12:04:20s -0:04:20 -
+Rule sol89 1989 only - Jul 5 12:04:30s -0:04:30 -
+Rule sol89 1989 only - Jul 6 12:04:40s -0:04:40 -
+Rule sol89 1989 only - Jul 7 12:04:50s -0:04:50 -
+Rule sol89 1989 only - Jul 8 12:05:00s -0:05:00 -
+Rule sol89 1989 only - Jul 9 12:05:10s -0:05:10 -
+Rule sol89 1989 only - Jul 10 12:05:20s -0:05:20 -
+Rule sol89 1989 only - Jul 11 12:05:25s -0:05:25 -
+Rule sol89 1989 only - Jul 12 12:05:35s -0:05:35 -
+Rule sol89 1989 only - Jul 13 12:05:40s -0:05:40 -
+Rule sol89 1989 only - Jul 14 12:05:50s -0:05:50 -
+Rule sol89 1989 only - Jul 15 12:05:55s -0:05:55 -
+Rule sol89 1989 only - Jul 16 12:06:00s -0:06:00 -
+Rule sol89 1989 only - Jul 17 12:06:05s -0:06:05 -
+Rule sol89 1989 only - Jul 18 12:06:10s -0:06:10 -
+Rule sol89 1989 only - Jul 19 12:06:15s -0:06:15 -
+Rule sol89 1989 only - Jul 20 12:06:20s -0:06:20 -
+Rule sol89 1989 only - Jul 21 12:06:20s -0:06:20 -
+Rule sol89 1989 only - Jul 22 12:06:25s -0:06:25 -
+Rule sol89 1989 only - Jul 23 12:06:25s -0:06:25 -
+Rule sol89 1989 only - Jul 24 12:06:30s -0:06:30 -
+Rule sol89 1989 only - Jul 25 12:06:30s -0:06:30 -
+Rule sol89 1989 only - Jul 26 12:06:30s -0:06:30 -
+Rule sol89 1989 only - Jul 27 12:06:30s -0:06:30 -
+Rule sol89 1989 only - Jul 28 12:06:30s -0:06:30 -
+Rule sol89 1989 only - Jul 29 12:06:25s -0:06:25 -
+Rule sol89 1989 only - Jul 30 12:06:25s -0:06:25 -
+Rule sol89 1989 only - Jul 31 12:06:20s -0:06:20 -
+Rule sol89 1989 only - Aug 1 12:06:20s -0:06:20 -
+Rule sol89 1989 only - Aug 2 12:06:15s -0:06:15 -
+Rule sol89 1989 only - Aug 3 12:06:10s -0:06:10 -
+Rule sol89 1989 only - Aug 4 12:06:05s -0:06:05 -
+Rule sol89 1989 only - Aug 5 12:06:00s -0:06:00 -
+Rule sol89 1989 only - Aug 6 12:05:50s -0:05:50 -
+Rule sol89 1989 only - Aug 7 12:05:45s -0:05:45 -
+Rule sol89 1989 only - Aug 8 12:05:35s -0:05:35 -
+Rule sol89 1989 only - Aug 9 12:05:30s -0:05:30 -
+Rule sol89 1989 only - Aug 10 12:05:20s -0:05:20 -
+Rule sol89 1989 only - Aug 11 12:05:10s -0:05:10 -
+Rule sol89 1989 only - Aug 12 12:05:00s -0:05:00 -
+Rule sol89 1989 only - Aug 13 12:04:50s -0:04:50 -
+Rule sol89 1989 only - Aug 14 12:04:40s -0:04:40 -
+Rule sol89 1989 only - Aug 15 12:04:30s -0:04:30 -
+Rule sol89 1989 only - Aug 16 12:04:15s -0:04:15 -
+Rule sol89 1989 only - Aug 17 12:04:05s -0:04:05 -
+Rule sol89 1989 only - Aug 18 12:03:50s -0:03:50 -
+Rule sol89 1989 only - Aug 19 12:03:35s -0:03:35 -
+Rule sol89 1989 only - Aug 20 12:03:25s -0:03:25 -
+Rule sol89 1989 only - Aug 21 12:03:10s -0:03:10 -
+Rule sol89 1989 only - Aug 22 12:02:55s -0:02:55 -
+Rule sol89 1989 only - Aug 23 12:02:40s -0:02:40 -
+Rule sol89 1989 only - Aug 24 12:02:20s -0:02:20 -
+Rule sol89 1989 only - Aug 25 12:02:05s -0:02:05 -
+Rule sol89 1989 only - Aug 26 12:01:50s -0:01:50 -
+Rule sol89 1989 only - Aug 27 12:01:30s -0:01:30 -
+Rule sol89 1989 only - Aug 28 12:01:15s -0:01:15 -
+Rule sol89 1989 only - Aug 29 12:00:55s -0:00:55 -
+Rule sol89 1989 only - Aug 30 12:00:40s -0:00:40 -
+Rule sol89 1989 only - Aug 31 12:00:20s -0:00:20 -
+Rule sol89 1989 only - Sep 1 12:00:00s 0:00:00 -
+Rule sol89 1989 only - Sep 2 11:59:45s 0:00:15 -
+Rule sol89 1989 only - Sep 3 11:59:25s 0:00:35 -
+Rule sol89 1989 only - Sep 4 11:59:05s 0:00:55 -
+Rule sol89 1989 only - Sep 5 11:58:45s 0:01:15 -
+Rule sol89 1989 only - Sep 6 11:58:25s 0:01:35 -
+Rule sol89 1989 only - Sep 7 11:58:05s 0:01:55 -
+Rule sol89 1989 only - Sep 8 11:57:45s 0:02:15 -
+Rule sol89 1989 only - Sep 9 11:57:20s 0:02:40 -
+Rule sol89 1989 only - Sep 10 11:57:00s 0:03:00 -
+Rule sol89 1989 only - Sep 11 11:56:40s 0:03:20 -
+Rule sol89 1989 only - Sep 12 11:56:20s 0:03:40 -
+Rule sol89 1989 only - Sep 13 11:56:00s 0:04:00 -
+Rule sol89 1989 only - Sep 14 11:55:35s 0:04:25 -
+Rule sol89 1989 only - Sep 15 11:55:15s 0:04:45 -
+Rule sol89 1989 only - Sep 16 11:54:55s 0:05:05 -
+Rule sol89 1989 only - Sep 17 11:54:35s 0:05:25 -
+Rule sol89 1989 only - Sep 18 11:54:10s 0:05:50 -
+Rule sol89 1989 only - Sep 19 11:53:50s 0:06:10 -
+Rule sol89 1989 only - Sep 20 11:53:30s 0:06:30 -
+Rule sol89 1989 only - Sep 21 11:53:10s 0:06:50 -
+Rule sol89 1989 only - Sep 22 11:52:45s 0:07:15 -
+Rule sol89 1989 only - Sep 23 11:52:25s 0:07:35 -
+Rule sol89 1989 only - Sep 24 11:52:05s 0:07:55 -
+Rule sol89 1989 only - Sep 25 11:51:45s 0:08:15 -
+Rule sol89 1989 only - Sep 26 11:51:25s 0:08:35 -
+Rule sol89 1989 only - Sep 27 11:51:05s 0:08:55 -
+Rule sol89 1989 only - Sep 28 11:50:40s 0:09:20 -
+Rule sol89 1989 only - Sep 29 11:50:20s 0:09:40 -
+Rule sol89 1989 only - Sep 30 11:50:00s 0:10:00 -
+Rule sol89 1989 only - Oct 1 11:49:45s 0:10:15 -
+Rule sol89 1989 only - Oct 2 11:49:25s 0:10:35 -
+Rule sol89 1989 only - Oct 3 11:49:05s 0:10:55 -
+Rule sol89 1989 only - Oct 4 11:48:45s 0:11:15 -
+Rule sol89 1989 only - Oct 5 11:48:30s 0:11:30 -
+Rule sol89 1989 only - Oct 6 11:48:10s 0:11:50 -
+Rule sol89 1989 only - Oct 7 11:47:50s 0:12:10 -
+Rule sol89 1989 only - Oct 8 11:47:35s 0:12:25 -
+Rule sol89 1989 only - Oct 9 11:47:20s 0:12:40 -
+Rule sol89 1989 only - Oct 10 11:47:00s 0:13:00 -
+Rule sol89 1989 only - Oct 11 11:46:45s 0:13:15 -
+Rule sol89 1989 only - Oct 12 11:46:30s 0:13:30 -
+Rule sol89 1989 only - Oct 13 11:46:15s 0:13:45 -
+Rule sol89 1989 only - Oct 14 11:46:00s 0:14:00 -
+Rule sol89 1989 only - Oct 15 11:45:50s 0:14:10 -
+Rule sol89 1989 only - Oct 16 11:45:35s 0:14:25 -
+Rule sol89 1989 only - Oct 17 11:45:20s 0:14:40 -
+Rule sol89 1989 only - Oct 18 11:45:10s 0:14:50 -
+Rule sol89 1989 only - Oct 19 11:45:00s 0:15:00 -
+Rule sol89 1989 only - Oct 20 11:44:50s 0:15:10 -
+Rule sol89 1989 only - Oct 21 11:44:40s 0:15:20 -
+Rule sol89 1989 only - Oct 22 11:44:30s 0:15:30 -
+Rule sol89 1989 only - Oct 23 11:44:20s 0:15:40 -
+Rule sol89 1989 only - Oct 24 11:44:10s 0:15:50 -
+Rule sol89 1989 only - Oct 25 11:44:05s 0:15:55 -
+Rule sol89 1989 only - Oct 26 11:44:00s 0:16:00 -
+Rule sol89 1989 only - Oct 27 11:43:50s 0:16:10 -
+Rule sol89 1989 only - Oct 28 11:43:45s 0:16:15 -
+Rule sol89 1989 only - Oct 29 11:43:40s 0:16:20 -
+Rule sol89 1989 only - Oct 30 11:43:40s 0:16:20 -
+Rule sol89 1989 only - Oct 31 11:43:35s 0:16:25 -
+Rule sol89 1989 only - Nov 1 11:43:35s 0:16:25 -
+Rule sol89 1989 only - Nov 2 11:43:35s 0:16:25 -
+Rule sol89 1989 only - Nov 3 11:43:30s 0:16:30 -
+Rule sol89 1989 only - Nov 4 11:43:35s 0:16:25 -
+Rule sol89 1989 only - Nov 5 11:43:35s 0:16:25 -
+Rule sol89 1989 only - Nov 6 11:43:35s 0:16:25 -
+Rule sol89 1989 only - Nov 7 11:43:40s 0:16:20 -
+Rule sol89 1989 only - Nov 8 11:43:45s 0:16:15 -
+Rule sol89 1989 only - Nov 9 11:43:50s 0:16:10 -
+Rule sol89 1989 only - Nov 10 11:43:55s 0:16:05 -
+Rule sol89 1989 only - Nov 11 11:44:00s 0:16:00 -
+Rule sol89 1989 only - Nov 12 11:44:05s 0:15:55 -
+Rule sol89 1989 only - Nov 13 11:44:15s 0:15:45 -
+Rule sol89 1989 only - Nov 14 11:44:25s 0:15:35 -
+Rule sol89 1989 only - Nov 15 11:44:35s 0:15:25 -
+Rule sol89 1989 only - Nov 16 11:44:45s 0:15:15 -
+Rule sol89 1989 only - Nov 17 11:44:55s 0:15:05 -
+Rule sol89 1989 only - Nov 18 11:45:10s 0:14:50 -
+Rule sol89 1989 only - Nov 19 11:45:20s 0:14:40 -
+Rule sol89 1989 only - Nov 20 11:45:35s 0:14:25 -
+Rule sol89 1989 only - Nov 21 11:45:50s 0:14:10 -
+Rule sol89 1989 only - Nov 22 11:46:05s 0:13:55 -
+Rule sol89 1989 only - Nov 23 11:46:25s 0:13:35 -
+Rule sol89 1989 only - Nov 24 11:46:40s 0:13:20 -
+Rule sol89 1989 only - Nov 25 11:47:00s 0:13:00 -
+Rule sol89 1989 only - Nov 26 11:47:20s 0:12:40 -
+Rule sol89 1989 only - Nov 27 11:47:35s 0:12:25 -
+Rule sol89 1989 only - Nov 28 11:47:55s 0:12:05 -
+Rule sol89 1989 only - Nov 29 11:48:20s 0:11:40 -
+Rule sol89 1989 only - Nov 30 11:48:40s 0:11:20 -
+Rule sol89 1989 only - Dec 1 11:49:00s 0:11:00 -
+Rule sol89 1989 only - Dec 2 11:49:25s 0:10:35 -
+Rule sol89 1989 only - Dec 3 11:49:50s 0:10:10 -
+Rule sol89 1989 only - Dec 4 11:50:15s 0:09:45 -
+Rule sol89 1989 only - Dec 5 11:50:35s 0:09:25 -
+Rule sol89 1989 only - Dec 6 11:51:00s 0:09:00 -
+Rule sol89 1989 only - Dec 7 11:51:30s 0:08:30 -
+Rule sol89 1989 only - Dec 8 11:51:55s 0:08:05 -
+Rule sol89 1989 only - Dec 9 11:52:20s 0:07:40 -
+Rule sol89 1989 only - Dec 10 11:52:50s 0:07:10 -
+Rule sol89 1989 only - Dec 11 11:53:15s 0:06:45 -
+Rule sol89 1989 only - Dec 12 11:53:45s 0:06:15 -
+Rule sol89 1989 only - Dec 13 11:54:10s 0:05:50 -
+Rule sol89 1989 only - Dec 14 11:54:40s 0:05:20 -
+Rule sol89 1989 only - Dec 15 11:55:10s 0:04:50 -
+Rule sol89 1989 only - Dec 16 11:55:40s 0:04:20 -
+Rule sol89 1989 only - Dec 17 11:56:05s 0:03:55 -
+Rule sol89 1989 only - Dec 18 11:56:35s 0:03:25 -
+Rule sol89 1989 only - Dec 19 11:57:05s 0:02:55 -
+Rule sol89 1989 only - Dec 20 11:57:35s 0:02:25 -
+Rule sol89 1989 only - Dec 21 11:58:05s 0:01:55 -
+Rule sol89 1989 only - Dec 22 11:58:35s 0:01:25 -
+Rule sol89 1989 only - Dec 23 11:59:05s 0:00:55 -
+Rule sol89 1989 only - Dec 24 11:59:35s 0:00:25 -
+Rule sol89 1989 only - Dec 25 12:00:05s -0:00:05 -
+Rule sol89 1989 only - Dec 26 12:00:35s -0:00:35 -
+Rule sol89 1989 only - Dec 27 12:01:05s -0:01:05 -
+Rule sol89 1989 only - Dec 28 12:01:35s -0:01:35 -
+Rule sol89 1989 only - Dec 29 12:02:00s -0:02:00 -
+Rule sol89 1989 only - Dec 30 12:02:30s -0:02:30 -
+Rule sol89 1989 only - Dec 31 12:03:00s -0:03:00 -
+
+# Riyadh is at about 46 degrees 46 minutes East: 3 hrs, 7 mins, 4 secs
+# Before and after 1989, we'll operate on local mean solar time.
+
+# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL]
+Zone Asia/Riyadh89 3:07:04 - zzz 1989
+ 3:07:04 sol89 zzz 1990
+ 3:07:04 - zzz
+# For backward compatibility...
+Link Asia/Riyadh89 Mideast/Riyadh89
diff --git a/tools/zoneinfo/tzdata2008h/southamerica b/tools/zoneinfo/tzdata2008h/southamerica
new file mode 100644
index 0000000..5dae61a
--- /dev/null
+++ b/tools/zoneinfo/tzdata2008h/southamerica
@@ -0,0 +1,1390 @@
+# @(#)southamerica 8.30
+# <pre>
+
+# This data is by no means authoritative; if you think you know better,
+# go ahead and edit the file (and please send any changes to
+# tz@elsie.nci.nih.gov for general use in the future).
+
+# From Paul Eggert (2006-03-22):
+# A good source for time zone historical data outside the U.S. is
+# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
+# San Diego: ACS Publications, Inc. (2003).
+#
+# Gwillim Law writes that a good source
+# for recent time zone data is the International Air Transport
+# Association's Standard Schedules Information Manual (IATA SSIM),
+# published semiannually. Law sent in several helpful summaries
+# of the IATA's data after 1990.
+#
+# Except where otherwise noted, Shanks & Pottenger is the source for
+# entries through 1990, and IATA SSIM is the source for entries afterwards.
+#
+# Earlier editions of these tables used the North American style (e.g. ARST and
+# ARDT for Argentine Standard and Daylight Time), but the following quote
+# suggests that it's better to use European style (e.g. ART and ARST).
+# I suggest the use of _Summer time_ instead of the more cumbersome
+# _daylight-saving time_. _Summer time_ seems to be in general use
+# in Europe and South America.
+# -- E O Cutler, _New York Times_ (1937-02-14), quoted in
+# H L Mencken, _The American Language: Supplement I_ (1960), p 466
+#
+# Earlier editions of these tables also used the North American style
+# for time zones in Brazil, but this was incorrect, as Brazilians say
+# "summer time". Reinaldo Goulart, a Sao Paulo businessman active in
+# the railroad sector, writes (1999-07-06):
+# The subject of time zones is currently a matter of discussion/debate in
+# Brazil. Let's say that "the Brasilia time" is considered the
+# "official time" because Brasilia is the capital city.
+# The other three time zones are called "Brasilia time "minus one" or
+# "plus one" or "plus two". As far as I know there is no such
+# name/designation as "Eastern Time" or "Central Time".
+# So I invented the following (English-language) abbreviations for now.
+# Corrections are welcome!
+# std dst
+# -2:00 FNT FNST Fernando de Noronha
+# -3:00 BRT BRST Brasilia
+# -4:00 AMT AMST Amazon
+# -5:00 ACT ACST Acre
+
+###############################################################################
+
+###############################################################################
+
+# Argentina
+
+# From Bob Devine (1988-01-28):
+# Argentina: first Sunday in October to first Sunday in April since 1976.
+# Double Summer time from 1969 to 1974. Switches at midnight.
+
+# From U. S. Naval Observatory (1988-01-199):
+# ARGENTINA 3 H BEHIND UTC
+
+# From Hernan G. Otero (1995-06-26):
+# I am sending modifications to the Argentine time zone table...
+# AR was chosen because they are the ISO letters that represent Argentina.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Arg 1930 only - Dec 1 0:00 1:00 S
+Rule Arg 1931 only - Apr 1 0:00 0 -
+Rule Arg 1931 only - Oct 15 0:00 1:00 S
+Rule Arg 1932 1940 - Mar 1 0:00 0 -
+Rule Arg 1932 1939 - Nov 1 0:00 1:00 S
+Rule Arg 1940 only - Jul 1 0:00 1:00 S
+Rule Arg 1941 only - Jun 15 0:00 0 -
+Rule Arg 1941 only - Oct 15 0:00 1:00 S
+Rule Arg 1943 only - Aug 1 0:00 0 -
+Rule Arg 1943 only - Oct 15 0:00 1:00 S
+Rule Arg 1946 only - Mar 1 0:00 0 -
+Rule Arg 1946 only - Oct 1 0:00 1:00 S
+Rule Arg 1963 only - Oct 1 0:00 0 -
+Rule Arg 1963 only - Dec 15 0:00 1:00 S
+Rule Arg 1964 1966 - Mar 1 0:00 0 -
+Rule Arg 1964 1966 - Oct 15 0:00 1:00 S
+Rule Arg 1967 only - Apr 2 0:00 0 -
+Rule Arg 1967 1968 - Oct Sun>=1 0:00 1:00 S
+Rule Arg 1968 1969 - Apr Sun>=1 0:00 0 -
+Rule Arg 1974 only - Jan 23 0:00 1:00 S
+Rule Arg 1974 only - May 1 0:00 0 -
+Rule Arg 1988 only - Dec 1 0:00 1:00 S
+#
+# From Hernan G. Otero (1995-06-26):
+# These corrections were contributed by InterSoft Argentina S.A.,
+# obtaining the data from the:
+# Talleres de Hidrografia Naval Argentina
+# (Argentine Naval Hydrography Institute)
+Rule Arg 1989 1993 - Mar Sun>=1 0:00 0 -
+Rule Arg 1989 1992 - Oct Sun>=15 0:00 1:00 S
+#
+# From Hernan G. Otero (1995-06-26):
+# From this moment on, the law that mandated the daylight saving
+# time corrections was derogated and no more modifications
+# to the time zones (for daylight saving) are now made.
+#
+# From Rives McDow (2000-01-10):
+# On October 3, 1999, 0:00 local, Argentina implemented daylight savings time,
+# which did not result in the switch of a time zone, as they stayed 9 hours
+# from the International Date Line.
+Rule Arg 1999 only - Oct Sun>=1 0:00 1:00 S
+# From Paul Eggert (2007-12-28):
+# DST was set to expire on March 5, not March 3, but since it was converted
+# to standard time on March 3 it's more convenient for us to pretend that
+# it ended on March 3.
+Rule Arg 2000 only - Mar 3 0:00 0 -
+#
+# From Peter Gradelski via Steffen Thorsen (2000-03-01):
+# We just checked with our Sao Paulo office and they say the government of
+# Argentina decided not to become one of the countries that go on or off DST.
+# So Buenos Aires should be -3 hours from GMT at all times.
+#
+# From Fabian L. Arce Jofre (2000-04-04):
+# The law that claimed DST for Argentina was derogated by President Fernando
+# de la Rua on March 2, 2000, because it would make people spend more energy
+# in the winter time, rather than less. The change took effect on March 3.
+#
+# From Mariano Absatz (2001-06-06):
+# one of the major newspapers here in Argentina said that the 1999
+# Timezone Law (which never was effectively applied) will (would?) be
+# in effect.... The article is at
+# http://ar.clarin.com/diario/2001-06-06/e-01701.htm
+# ... The Law itself is "Ley No 25155", sanctioned on 1999-08-25, enacted
+# 1999-09-17, and published 1999-09-21. The official publication is at:
+# http://www.boletin.jus.gov.ar/BON/Primera/1999/09-Septiembre/21/PDF/BO21-09-99LEG.PDF
+# Regretfully, you have to subscribe (and pay) for the on-line version....
+#
+# (2001-06-12):
+# the timezone for Argentina will not change next Sunday.
+# Apparently it will do so on Sunday 24th....
+# http://ar.clarin.com/diario/2001-06-12/s-03501.htm
+#
+# (2001-06-25):
+# Last Friday (yes, the last working day before the date of the change), the
+# Senate annulled the 1999 law that introduced the changes later postponed.
+# http://www.clarin.com.ar/diario/2001-06-22/s-03601.htm
+# It remains the vote of the Deputies..., but it will be the same....
+# This kind of things had always been done this way in Argentina.
+# We are still -03:00 all year round in all of the country.
+#
+# From Steffen Thorsen (2007-12-21):
+# A user (Leonardo Chaim) reported that Argentina will adopt DST....
+# all of the country (all Zone-entries) are affected. News reports like
+# http://www.lanacion.com.ar/opinion/nota.asp?nota_id=973037 indicate
+# that Argentina will use DST next year as well, from October to
+# March, although exact rules are not given.
+#
+# From Jesper Norgaard Welen (2007-12-26)
+# The last hurdle of Argentina DST is over, the proposal was approved in
+# the lower chamber too (Deputados) with a vote 192 for and 2 against.
+# By the way thanks to Mariano Absatz and Daniel Mario Vega for the link to
+# the original scanned proposal, where the dates and the zero hours are
+# clear and unambiguous...This is the article about final approval:
+# <a href="http://www.lanacion.com.ar/politica/nota.asp?nota_id=973996">
+# http://www.lanacion.com.ar/politica/nota.asp?nota_id=973996
+# </a>
+#
+# From Paul Eggert (2007-12-22):
+# For dates after mid-2008, the following rules are my guesses and
+# are quite possibly wrong, but are more likely than no DST at all.
+
+# From Alexander Krivenyshev (2008-09-05):
+# As per message from Carlos Alberto Fonseca Arauz (Nicaragua),
+# Argentina will start DST on Sunday October 19, 2008.
+#
+# <a href="http://www.worldtimezone.com/dst_news/dst_news_argentina03.html">
+# http://www.worldtimezone.com/dst_news/dst_news_argentina03.html
+# </a>
+# OR
+# <a href="http://www.impulsobaires.com.ar/nota.php?id=57832 (in spanish)">
+# http://www.impulsobaires.com.ar/nota.php?id=57832 (in spanish)
+# </a>
+
+# From Rodrigo Severo (2008-10-06):
+# Here is some info available at a Gentoo bug related to TZ on Argentina's DST:
+# ...
+# ------- Comment #1 from [jmdocile] 2008-10-06 16:28 0000 -------
+# Hi, there is a problem with timezone-data-2008e and maybe with
+# timezone-data-2008f
+# Argentinian law [Number] 25.155 is no longer valid.
+# <a href="http://www.infoleg.gov.ar/infolegInternet/anexos/60000-64999/60036/norma.htm">
+# http://www.infoleg.gov.ar/infolegInternet/anexos/60000-64999/60036/norma.htm
+# </a>
+# The new one is law [Number] 26.350
+# <a href="http://www.infoleg.gov.ar/infolegInternet/anexos/135000-139999/136191/norma.htm">
+# http://www.infoleg.gov.ar/infolegInternet/anexos/135000-139999/136191/norma.htm
+# </a>
+# So there is no summer time in Argentina for now.
+
+Rule Arg 2007 only - Dec 30 0:00 1:00 S
+Rule Arg 2008 max - Mar Sun>=15 0:00 0 -
+Rule Arg 2008 max - Oct Sun>=15 0:00 1:00 S
+
+# From Mariano Absatz (2004-05-21):
+# Today it was officially published that the Province of Mendoza is changing
+# its timezone this winter... starting tomorrow night....
+# http://www.gobernac.mendoza.gov.ar/boletin/pdf/20040521-27158-normas.pdf
+# From Paul Eggert (2004-05-24):
+# It's Law No. 7,210. This change is due to a public power emergency, so for
+# now we'll assume it's for this year only.
+#
+# From Paul Eggert (2006-03-22):
+# <a href="http://www.spicasc.net/horvera.html">
+# Hora de verano para la Republica Argentina (2003-06-08)
+# </a> says that standard time in Argentina from 1894-10-31
+# to 1920-05-01 was -4:16:48.25. Go with this more-precise value
+# over Shanks & Pottenger.
+#
+# From Mariano Absatz (2004-06-05):
+# These media articles from a major newspaper mostly cover the current state:
+# http://www.lanacion.com.ar/04/05/27/de_604825.asp
+# http://www.lanacion.com.ar/04/05/28/de_605203.asp
+#
+# The following eight (8) provinces pulled clocks back to UTC-04:00 at
+# midnight Monday May 31st. (that is, the night between 05/31 and 06/01).
+# Apparently, all nine provinces would go back to UTC-03:00 at the same
+# time in October 17th.
+#
+# Catamarca, Chubut, La Rioja, San Juan, San Luis, Santa Cruz,
+# Tierra del Fuego, Tucuman.
+#
+# From Mariano Absatz (2004-06-14):
+# ... this weekend, the Province of Tucuman decided it'd go back to UTC-03:00
+# yesterday midnight (that is, at 24:00 Saturday 12th), since the people's
+# annoyance with the change is much higher than the power savings obtained....
+#
+# From Gwillim Law (2004-06-14):
+# http://www.lanacion.com.ar/04/06/10/de_609078.asp ...
+# "The time change in Tierra del Fuego was a conflicted decision from
+# the start. The government had decreed that the measure would take
+# effect on June 1, but a normative error forced the new time to begin
+# three days earlier, from a Saturday to a Sunday....
+# Our understanding was that the change was originally scheduled to take place
+# on June 1 at 00:00 in Chubut, Santa Cruz, Tierra del Fuego (and some other
+# provinces). Sunday was May 30, only two days earlier. So the article
+# contains a contradiction. I would give more credence to the Saturday/Sunday
+# date than the "three days earlier" phrase, and conclude that Tierra del
+# Fuego set its clocks back at 2004-05-30 00:00.
+#
+# From Steffen Thorsen (2004-10-05):
+# The previous law 7210 which changed the province of Mendoza's time zone
+# back in May have been modified slightly in a new law 7277, which set the
+# new end date to 2004-09-26 (original date was 2004-10-17).
+# http://www.gobernac.mendoza.gov.ar/boletin/pdf/20040924-27244-normas.pdf
+#
+# From Mariano Absatz (2004-10-05):
+# San Juan changed from UTC-03:00 to UTC-04:00 at midnight between
+# Sunday, May 30th and Monday, May 31st. It changed back to UTC-03:00
+# at midnight between Saturday, July 24th and Sunday, July 25th....
+# http://www.sanjuan.gov.ar/prensa/archivo/000329.html
+# http://www.sanjuan.gov.ar/prensa/archivo/000426.html
+# http://www.sanjuan.gov.ar/prensa/archivo/000441.html
+
+# From Alex Krivenyshev (2008-01-17):
+# Here are articles that Argentina Province San Luis is planning to end DST
+# as earlier as upcoming Monday January 21, 2008 or February 2008:
+#
+# Provincia argentina retrasa reloj y marca diferencia con resto del pais
+# (Argentine Province delayed clock and mark difference with the rest of the
+# country)
+# <a href="http://cl.invertia.com/noticias/noticia.aspx?idNoticia=200801171849_EFE_ET4373&idtel">
+# http://cl.invertia.com/noticias/noticia.aspx?idNoticia=200801171849_EFE_ET4373&idtel
+# </a>
+#
+# Es inminente que en San Luis atrasen una hora los relojes
+# (It is imminent in San Luis clocks one hour delay)
+# <a href="http://www.lagaceta.com.ar/vernotae.asp?id_nota=253414">
+# http://www.lagaceta.com.ar/vernotae.asp?id_nota=253414
+# </a>
+#
+# <a href="http://www.worldtimezone.net/dst_news/dst_news_argentina02.html">
+# http://www.worldtimezone.net/dst_news/dst_news_argentina02.html
+# </a>
+
+# From Jesper Norgaard Welen (2008-01-18):
+# The page of the San Luis provincial government
+# <a href="http://www.sanluis.gov.ar/notas.asp?idCanal=0&id=22812">
+# http://www.sanluis.gov.ar/notas.asp?idCanal=0&id=22812
+# </a>
+# confirms what Alex Krivenyshev has earlier sent to the tz
+# emailing list about that San Luis plans to return to standard
+# time much earlier than the rest of the country. It also
+# confirms that upon request the provinces San Juan and Mendoza
+# refused to follow San Luis in this change.
+#
+# The change is supposed to take place Monday the 21.st at 0:00
+# hours. As far as I understand it if this goes ahead, we need
+# a new timezone for San Luis (although there are also documented
+# independent changes in the southamerica file of San Luis in
+# 1990 and 1991 which has not been confirmed).
+
+# From Jesper Norgaard Welen (2008-01-25):
+# Unfortunately the below page has become defunct, about the San Luis
+# time change. Perhaps because it now is part of a group of pages "Most
+# important pages of 2008."
+#
+# You can use
+# <a href="http://www.sanluis.gov.ar/notas.asp?idCanal=8141&id=22834">
+# http://www.sanluis.gov.ar/notas.asp?idCanal=8141&id=22834
+# </a>
+# instead it seems. Or use "Buscador" from the main page of the San Luis
+# government, and fill in "huso" and click OK, and you will get 3 pages
+# from which the first one is identical to the above.
+
+# From Mariano Absatz (2008-01-28):
+# I can confirm that the Province of San Luis (and so far only that
+# province) decided to go back to UTC-3 effective midnight Jan 20th 2008
+# (that is, Monday 21st at 0:00 is the time the clocks were delayed back
+# 1 hour), and they intend to keep UTC-3 as their timezone all year round
+# (that is, unless they change their mind any minute now).
+#
+# So we'll have to add yet another city to 'southamerica' (I think San
+# Luis city is the mos populated city in the Province, so it'd be
+# America/Argentina/San_Luis... of course I can't remember if San Luis's
+# history of particular changes goes along with Mendoza or San Juan :-(
+# (I only remember not being able to collect hard facts about San Luis
+# back in 2004, when these provinces changed to UTC-4 for a few days, I
+# mailed them personally and never got an answer).
+
+# From Paul Eggert (2008-06-30):
+# Unless otherwise specified, data are from Shanks & Pottenger through 1992,
+# from the IATA otherwise. As noted below, Shanks & Pottenger say that
+# America/Cordoba split into 6 subregions during 1991/1992, one of which
+# was America/San_Luis, but we haven't verified this yet so for now we'll
+# keep America/Cordoba a single region rather than splitting it into the
+# other 5 subregions.
+
+#
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+#
+# Buenos Aires (BA), Capital Federal (CF),
+Zone America/Argentina/Buenos_Aires -3:53:48 - LMT 1894 Oct 31
+ -4:16:48 - CMT 1920 May # Cordoba Mean Time
+ -4:00 - ART 1930 Dec
+ -4:00 Arg AR%sT 1969 Oct 5
+ -3:00 Arg AR%sT 1999 Oct 3
+ -4:00 Arg AR%sT 2000 Mar 3
+ -3:00 Arg AR%sT
+#
+# Santa Fe (SF), Entre Rios (ER), Corrientes (CN), Misiones (MN), Chaco (CC),
+# Formosa (FM), Salta (SA), Santiago del Estero (SE), Cordoba (CB),
+# La Pampa (LP), Neuquen (NQ), Rio Negro (RN)
+#
+# Shanks & Pottenger also make the following claims, which we haven't verified:
+# - Formosa switched to -3:00 on 1991-01-07.
+# - Misiones switched to -3:00 on 1990-12-29.
+# - Chaco switched to -3:00 on 1991-01-04.
+# - Santiago del Estero switched to -4:00 on 1991-04-01,
+# then to -3:00 on 1991-04-26.
+#
+Zone America/Argentina/Cordoba -4:16:48 - LMT 1894 Oct 31
+ -4:16:48 - CMT 1920 May
+ -4:00 - ART 1930 Dec
+ -4:00 Arg AR%sT 1969 Oct 5
+ -3:00 Arg AR%sT 1991 Mar 3
+ -4:00 - WART 1991 Oct 20
+ -3:00 Arg AR%sT 1999 Oct 3
+ -4:00 Arg AR%sT 2000 Mar 3
+ -3:00 Arg AR%sT
+#
+# Tucuman (TM)
+Zone America/Argentina/Tucuman -4:20:52 - LMT 1894 Oct 31
+ -4:16:48 - CMT 1920 May
+ -4:00 - ART 1930 Dec
+ -4:00 Arg AR%sT 1969 Oct 5
+ -3:00 Arg AR%sT 1991 Mar 3
+ -4:00 - WART 1991 Oct 20
+ -3:00 Arg AR%sT 1999 Oct 3
+ -4:00 Arg AR%sT 2000 Mar 3
+ -3:00 - ART 2004 Jun 1
+ -4:00 - WART 2004 Jun 13
+ -3:00 Arg AR%sT
+#
+# La Rioja (LR)
+Zone America/Argentina/La_Rioja -4:27:24 - LMT 1894 Oct 31
+ -4:16:48 - CMT 1920 May
+ -4:00 - ART 1930 Dec
+ -4:00 Arg AR%sT 1969 Oct 5
+ -3:00 Arg AR%sT 1991 Mar 1
+ -4:00 - WART 1991 May 7
+ -3:00 Arg AR%sT 1999 Oct 3
+ -4:00 Arg AR%sT 2000 Mar 3
+ -3:00 - ART 2004 Jun 1
+ -4:00 - WART 2004 Jun 20
+ -3:00 Arg AR%sT
+#
+# San Juan (SJ)
+Zone America/Argentina/San_Juan -4:34:04 - LMT 1894 Oct 31
+ -4:16:48 - CMT 1920 May
+ -4:00 - ART 1930 Dec
+ -4:00 Arg AR%sT 1969 Oct 5
+ -3:00 Arg AR%sT 1991 Mar 1
+ -4:00 - WART 1991 May 7
+ -3:00 Arg AR%sT 1999 Oct 3
+ -4:00 Arg AR%sT 2000 Mar 3
+ -3:00 - ART 2004 May 31
+ -4:00 - WART 2004 Jul 25
+ -3:00 Arg AR%sT
+#
+# Jujuy (JY)
+Zone America/Argentina/Jujuy -4:21:12 - LMT 1894 Oct 31
+ -4:16:48 - CMT 1920 May
+ -4:00 - ART 1930 Dec
+ -4:00 Arg AR%sT 1969 Oct 5
+ -3:00 Arg AR%sT 1990 Mar 4
+ -4:00 - WART 1990 Oct 28
+ -4:00 1:00 WARST 1991 Mar 17
+ -4:00 - WART 1991 Oct 6
+ -3:00 1:00 ARST 1992
+ -3:00 Arg AR%sT 1999 Oct 3
+ -4:00 Arg AR%sT 2000 Mar 3
+ -3:00 Arg AR%sT
+#
+# Catamarca (CT), Chubut (CH)
+Zone America/Argentina/Catamarca -4:23:08 - LMT 1894 Oct 31
+ -4:16:48 - CMT 1920 May
+ -4:00 - ART 1930 Dec
+ -4:00 Arg AR%sT 1969 Oct 5
+ -3:00 Arg AR%sT 1991 Mar 3
+ -4:00 - WART 1991 Oct 20
+ -3:00 Arg AR%sT 1999 Oct 3
+ -4:00 Arg AR%sT 2000 Mar 3
+ -3:00 - ART 2004 Jun 1
+ -4:00 - WART 2004 Jun 20
+ -3:00 Arg AR%sT
+#
+# Mendoza (MZ)
+Zone America/Argentina/Mendoza -4:35:16 - LMT 1894 Oct 31
+ -4:16:48 - CMT 1920 May
+ -4:00 - ART 1930 Dec
+ -4:00 Arg AR%sT 1969 Oct 5
+ -3:00 Arg AR%sT 1990 Mar 4
+ -4:00 - WART 1990 Oct 15
+ -4:00 1:00 WARST 1991 Mar 1
+ -4:00 - WART 1991 Oct 15
+ -4:00 1:00 WARST 1992 Mar 1
+ -4:00 - WART 1992 Oct 18
+ -3:00 Arg AR%sT 1999 Oct 3
+ -4:00 Arg AR%sT 2000 Mar 3
+ -3:00 - ART 2004 May 23
+ -4:00 - WART 2004 Sep 26
+ -3:00 Arg AR%sT
+#
+# San Luis (SL)
+Zone America/Argentina/San_Luis -4:25:24 - LMT 1894 Oct 31
+ -4:16:48 - CMT 1920 May
+ -4:00 - ART 1930 Dec
+ -4:00 Arg AR%sT 1969 Oct 5
+ -3:00 Arg AR%sT 1990
+ -3:00 1:00 ARST 1990 Mar 14
+ -4:00 - WART 1990 Oct 15
+ -4:00 1:00 WARST 1991 Mar 1
+ -4:00 - WART 1991 Jun 1
+ -3:00 - ART 1999 Oct 3
+ -4:00 1:00 WARST 2000 Mar 3
+ -3:00 - ART 2004 May 31
+ -4:00 - WART 2004 Jul 25
+ -3:00 Arg AR%sT 2008 Jan 21
+ -3:00 - ART
+#
+# Santa Cruz (SC)
+Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT 1894 Oct 31
+ -4:16:48 - CMT 1920 May # Cordoba Mean Time
+ -4:00 - ART 1930 Dec
+ -4:00 Arg AR%sT 1969 Oct 5
+ -3:00 Arg AR%sT 1999 Oct 3
+ -4:00 Arg AR%sT 2000 Mar 3
+ -3:00 - ART 2004 Jun 1
+ -4:00 - WART 2004 Jun 20
+ -3:00 Arg AR%sT
+#
+# Tierra del Fuego, Antartida e Islas del Atlantico Sur (TF)
+Zone America/Argentina/Ushuaia -4:33:12 - LMT 1894 Oct 31
+ -4:16:48 - CMT 1920 May # Cordoba Mean Time
+ -4:00 - ART 1930 Dec
+ -4:00 Arg AR%sT 1969 Oct 5
+ -3:00 Arg AR%sT 1999 Oct 3
+ -4:00 Arg AR%sT 2000 Mar 3
+ -3:00 - ART 2004 May 30
+ -4:00 - WART 2004 Jun 20
+ -3:00 Arg AR%sT
+
+# Aruba
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Aruba -4:40:24 - LMT 1912 Feb 12 # Oranjestad
+ -4:30 - ANT 1965 # Netherlands Antilles Time
+ -4:00 - AST
+
+# Bolivia
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/La_Paz -4:32:36 - LMT 1890
+ -4:32:36 - CMT 1931 Oct 15 # Calamarca MT
+ -4:32:36 1:00 BOST 1932 Mar 21 # Bolivia ST
+ -4:00 - BOT # Bolivia Time
+
+# Brazil
+
+# From Paul Eggert (1993-11-18):
+# The mayor of Rio recently attempted to change the time zone rules
+# just in his city, in order to leave more summer time for the tourist trade.
+# The rule change lasted only part of the day;
+# the federal government refused to follow the city's rules, and business
+# was in a chaos, so the mayor backed down that afternoon.
+
+# From IATA SSIM (1996-02):
+# _Only_ the following states in BR1 observe DST: Rio Grande do Sul (RS),
+# Santa Catarina (SC), Parana (PR), Sao Paulo (SP), Rio de Janeiro (RJ),
+# Espirito Santo (ES), Minas Gerais (MG), Bahia (BA), Goias (GO),
+# Distrito Federal (DF), Tocantins (TO), Sergipe [SE] and Alagoas [AL].
+# [The last three states are new to this issue of the IATA SSIM.]
+
+# From Gwillim Law (1996-10-07):
+# Geography, history (Tocantins was part of Goias until 1989), and other
+# sources of time zone information lead me to believe that AL, SE, and TO were
+# always in BR1, and so the only change was whether or not they observed DST....
+# The earliest issue of the SSIM I have is 2/91. Each issue from then until
+# 9/95 says that DST is observed only in the ten states I quoted from 9/95,
+# along with Mato Grosso (MT) and Mato Grosso do Sul (MS), which are in BR2
+# (UTC-4).... The other two time zones given for Brazil are BR3, which is
+# UTC-5, no DST, and applies only in the state of Acre (AC); and BR4, which is
+# UTC-2, and applies to Fernando de Noronha (formerly FN, but I believe it's
+# become part of the state of Pernambuco). The boundary between BR1 and BR2
+# has never been clearly stated. They've simply been called East and West.
+# However, some conclusions can be drawn from another IATA manual: the Airline
+# Coding Directory, which lists close to 400 airports in Brazil. For each
+# airport it gives a time zone which is coded to the SSIM. From that
+# information, I'm led to conclude that the states of Amapa (AP), Ceara (CE),
+# Maranhao (MA), Paraiba (PR), Pernambuco (PE), Piaui (PI), and Rio Grande do
+# Norte (RN), and the eastern part of Para (PA) are all in BR1 without DST.
+
+# From Marcos Tadeu (1998-09-27):
+# <a href="http://pcdsh01.on.br/verao1.html">
+# Brazilian official page
+# </a>
+
+# From Jesper Norgaard (2000-11-03):
+# [For an official list of which regions in Brazil use which time zones, see:]
+# http://pcdsh01.on.br/Fusbr.htm
+# http://pcdsh01.on.br/Fusbrhv.htm
+
+# From Celso Doria via David Madeo (2002-10-09):
+# The reason for the delay this year has to do with elections in Brazil.
+#
+# Unlike in the United States, elections in Brazil are 100% computerized and
+# the results are known almost immediately. Yesterday, it was the first
+# round of the elections when 115 million Brazilians voted for President,
+# Governor, Senators, Federal Deputies, and State Deputies. Nobody is
+# counting (or re-counting) votes anymore and we know there will be a second
+# round for the Presidency and also for some Governors. The 2nd round will
+# take place on October 27th.
+#
+# The reason why the DST will only begin November 3rd is that the thousands
+# of electoral machines used cannot have their time changed, and since the
+# Constitution says the elections must begin at 8:00 AM and end at 5:00 PM,
+# the Government decided to postpone DST, instead of changing the Constitution
+# (maybe, for the next elections, it will be possible to change the clock)...
+
+# From Rodrigo Severo (2004-10-04):
+# It's just the biannual change made necessary by the much hyped, supposedly
+# modern Brazilian eletronic voting machines which, apparently, can't deal
+# with a time change between the first and the second rounds of the elections.
+
+# From Steffen Thorsen (2007-09-20):
+# Brazil will start DST on 2007-10-14 00:00 and end on 2008-02-17 00:00:
+# http://www.mme.gov.br/site/news/detail.do;jsessionid=BBA06811AFCAAC28F0285210913513DA?newsId=13975
+
+# From Paul Schulze (2008-06-24):
+# ...by law number 11.662 of April 24, 2008 (published in the "Diario
+# Oficial da Uniao"...) in Brazil there are changes in the timezones,
+# effective today (00:00am at June 24, 2008) as follows:
+#
+# a) The timezone UTC+5 is e[x]tinguished, with all the Acre state and the
+# part of the Amazonas state that had this timezone now being put to the
+# timezone UTC+4
+# b) The whole Para state now is put at timezone UTC+3, instead of just
+# part of it, as was before.
+#
+# This change follows a proposal of senator Tiao Viana of Acre state, that
+# proposed it due to concerns about open television channels displaying
+# programs inappropriate to youths in the states that had the timezone
+# UTC+5 too early in the night. In the occasion, some more corrections
+# were proposed, trying to unify the timezones of any given state. This
+# change modifies timezone rules defined in decree 2.784 of 18 June,
+# 1913.
+
+# From Rodrigo Severo (2008-06-24):
+# Just correcting the URL:
+# <a href="https://www.in.gov.br/imprensa/visualiza/index.jsp?jornal=3Ddo&secao=3D1&pagina=3D1&data=3D25/04/2008">
+# https://www.in.gov.br/imprensa/visualiza/index.jsp?jornal=3Ddo&secao=3D1&pagina=3D1&data=3D25/04/2008
+# </a>
+#
+# As a result of the above Decree I believe the America/Rio_Branco
+# timezone shall be modified from UTC-5 to UTC-4 and a new timezone shall
+# be created to represent the the west side of the Para State. I
+# suggest this new timezone be called Santarem as the most
+# important/populated city in the affected area.
+#
+# This new timezone would be the same as the Rio_Branco timezone up to
+# the 2008/06/24 change which would be to UTC-3 instead of UTC-4.
+
+# From Alex Krivenyshev (2008-06-24):
+# This is a quick reference page for New and Old Brazil Time Zones map.
+# <a href="http://www.worldtimezone.com/brazil-time-new-old.php">
+# http://www.worldtimezone.com/brazil-time-new-old.php
+# </a>
+#
+# - 4 time zones replaced by 3 time zones-eliminating time zone UTC- 05
+# (state Acre and the part of the Amazonas will be UTC/GMT- 04) - western
+# part of Par state is moving to one timezone UTC- 03 (from UTC -04).
+
+# From Paul Eggert (2002-10-10):
+# The official decrees referenced below are mostly taken from
+# <a href="http://pcdsh01.on.br/DecHV.html">
+# Decretos sobre o Horario de Verao no Brasil
+# </a>.
+
+# From Steffen Thorsen (2008-08-29):
+# As announced by the government and many newspapers in Brazil late
+# yesterday, Brazil will start DST on 2008-10-19 (need to change rule) and
+# it will end on 2009-02-15 (current rule for Brazil is fine). Based on
+# past years experience with the elections, there was a good chance that
+# the start was postponed to November, but it did not happen this year.
+#
+# It has not yet been posted to http://pcdsh01.on.br/DecHV.html
+#
+# An official page about it:
+# <a href="http://www.mme.gov.br/site/news/detail.do?newsId=16722">
+# http://www.mme.gov.br/site/news/detail.do?newsId=16722
+# </a>
+# Note that this link does not always work directly, but must be accessed
+# by going to
+# <a href="http://www.mme.gov.br/first">
+# http://www.mme.gov.br/first
+# </a>
+#
+# One example link that works directly:
+# <a href="http://jornale.com.br/index.php?option=com_content&task=view&id=13530&Itemid=54">
+# http://jornale.com.br/index.php?option=com_content&task=view&id=13530&Itemid=54
+# (Portuguese)
+# </a>
+#
+# We have a written a short article about it as well:
+# <a href="http://www.timeanddate.com/news/time/brazil-dst-2008-2009.html">
+# http://www.timeanddate.com/news/time/brazil-dst-2008-2009.html
+# </a>
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+# Decree <a href="http://pcdsh01.on.br/HV20466.htm">20,466</a> (1931-10-01)
+# Decree <a href="http://pcdsh01.on.br/HV21896.htm">21,896</a> (1932-01-10)
+Rule Brazil 1931 only - Oct 3 11:00 1:00 S
+Rule Brazil 1932 1933 - Apr 1 0:00 0 -
+Rule Brazil 1932 only - Oct 3 0:00 1:00 S
+# Decree <a href="http://pcdsh01.on.br/HV23195.htm">23,195</a> (1933-10-10)
+# revoked DST.
+# Decree <a href="http://pcdsh01.on.br/HV27496.htm">27,496</a> (1949-11-24)
+# Decree <a href="http://pcdsh01.on.br/HV27998.htm">27,998</a> (1950-04-13)
+Rule Brazil 1949 1952 - Dec 1 0:00 1:00 S
+Rule Brazil 1950 only - Apr 16 1:00 0 -
+Rule Brazil 1951 1952 - Apr 1 0:00 0 -
+# Decree <a href="http://pcdsh01.on.br/HV32308.htm">32,308</a> (1953-02-24)
+Rule Brazil 1953 only - Mar 1 0:00 0 -
+# Decree <a href="http://pcdsh01.on.br/HV34724.htm">34,724</a> (1953-11-30)
+# revoked DST.
+# Decree <a href="http://pcdsh01.on.br/HV52700.htm">52,700</a> (1963-10-18)
+# established DST from 1963-10-23 00:00 to 1964-02-29 00:00
+# in SP, RJ, GB, MG, ES, due to the prolongation of the drought.
+# Decree <a href="http://pcdsh01.on.br/HV53071.htm">53,071</a> (1963-12-03)
+# extended the above decree to all of the national territory on 12-09.
+Rule Brazil 1963 only - Dec 9 0:00 1:00 S
+# Decree <a href="http://pcdsh01.on.br/HV53604.htm">53,604</a> (1964-02-25)
+# extended summer time by one day to 1964-03-01 00:00 (start of school).
+Rule Brazil 1964 only - Mar 1 0:00 0 -
+# Decree <a href="http://pcdsh01.on.br/HV55639.htm">55,639</a> (1965-01-27)
+Rule Brazil 1965 only - Jan 31 0:00 1:00 S
+Rule Brazil 1965 only - Mar 31 0:00 0 -
+# Decree <a href="http://pcdsh01.on.br/HV57303.htm">57,303</a> (1965-11-22)
+Rule Brazil 1965 only - Dec 1 0:00 1:00 S
+# Decree <a href="http://pcdsh01.on.br/HV57843.htm">57,843</a> (1966-02-18)
+Rule Brazil 1966 1968 - Mar 1 0:00 0 -
+Rule Brazil 1966 1967 - Nov 1 0:00 1:00 S
+# Decree <a href="http://pcdsh01.on.br/HV63429.htm">63,429</a> (1968-10-15)
+# revoked DST.
+# Decree <a href="http://pcdsh01.on.br/HV91698.htm">91,698</a> (1985-09-27)
+Rule Brazil 1985 only - Nov 2 0:00 1:00 S
+# Decree 92,310 (1986-01-21)
+# Decree 92,463 (1986-03-13)
+Rule Brazil 1986 only - Mar 15 0:00 0 -
+# Decree 93,316 (1986-10-01)
+Rule Brazil 1986 only - Oct 25 0:00 1:00 S
+Rule Brazil 1987 only - Feb 14 0:00 0 -
+# Decree <a href="http://pcdsh01.on.br/HV94922.htm">94,922</a> (1987-09-22)
+Rule Brazil 1987 only - Oct 25 0:00 1:00 S
+Rule Brazil 1988 only - Feb 7 0:00 0 -
+# Decree <a href="http://pcdsh01.on.br/HV96676.htm">96,676</a> (1988-09-12)
+# except for the states of AC, AM, PA, RR, RO, and AP (then a territory)
+Rule Brazil 1988 only - Oct 16 0:00 1:00 S
+Rule Brazil 1989 only - Jan 29 0:00 0 -
+# Decree <a href="http://pcdsh01.on.br/HV98077.htm">98,077</a> (1989-08-21)
+# with the same exceptions
+Rule Brazil 1989 only - Oct 15 0:00 1:00 S
+Rule Brazil 1990 only - Feb 11 0:00 0 -
+# Decree <a href="http://pcdsh01.on.br/HV99530.htm">99,530</a> (1990-09-17)
+# adopted by RS, SC, PR, SP, RJ, ES, MG, GO, MS, DF.
+# Decree 99,629 (1990-10-19) adds BA, MT.
+Rule Brazil 1990 only - Oct 21 0:00 1:00 S
+Rule Brazil 1991 only - Feb 17 0:00 0 -
+# <a href="http://pcdsh01.on.br/HV1991.htm">Unnumbered decree</a> (1991-09-25)
+# adopted by RS, SC, PR, SP, RJ, ES, MG, BA, GO, MT, MS, DF.
+Rule Brazil 1991 only - Oct 20 0:00 1:00 S
+Rule Brazil 1992 only - Feb 9 0:00 0 -
+# <a href="http://pcdsh01.on.br/HV1992.htm">Unnumbered decree</a> (1992-10-16)
+# adopted by same states.
+Rule Brazil 1992 only - Oct 25 0:00 1:00 S
+Rule Brazil 1993 only - Jan 31 0:00 0 -
+# Decree <a href="http://pcdsh01.on.br/HV942.htm">942</a> (1993-09-28)
+# adopted by same states, plus AM.
+# Decree <a href="http://pcdsh01.on.br/HV1252.htm">1,252</a> (1994-09-22;
+# web page corrected 2004-01-07) adopted by same states, minus AM.
+# Decree <a href="http://pcdsh01.on.br/HV1636.htm">1,636</a> (1995-09-14)
+# adopted by same states, plus MT and TO.
+# Decree <a href="http://pcdsh01.on.br/HV1674.htm">1,674</a> (1995-10-13)
+# adds AL, SE.
+Rule Brazil 1993 1995 - Oct Sun>=11 0:00 1:00 S
+Rule Brazil 1994 1995 - Feb Sun>=15 0:00 0 -
+Rule Brazil 1996 only - Feb 11 0:00 0 -
+# Decree <a href="http://pcdsh01.on.br/HV2000.htm">2,000</a> (1996-09-04)
+# adopted by same states, minus AL, SE.
+Rule Brazil 1996 only - Oct 6 0:00 1:00 S
+Rule Brazil 1997 only - Feb 16 0:00 0 -
+# From Daniel C. Sobral (1998-02-12):
+# In 1997, the DS began on October 6. The stated reason was that
+# because international television networks ignored Brazil's policy on DS,
+# they bought the wrong times on satellite for coverage of Pope's visit.
+# This year, the ending date of DS was postponed to March 1
+# to help dealing with the shortages of electric power.
+#
+# Decree 2,317 (1997-09-04), adopted by same states.
+Rule Brazil 1997 only - Oct 6 0:00 1:00 S
+# Decree <a href="http://pcdsh01.on.br/figuras/HV2495.JPG">2,495</a>
+# (1998-02-10)
+Rule Brazil 1998 only - Mar 1 0:00 0 -
+# Decree <a href="http://pcdsh01.on.br/figuras/Hv98.jpg">2,780</a> (1998-09-11)
+# adopted by the same states as before.
+Rule Brazil 1998 only - Oct 11 0:00 1:00 S
+Rule Brazil 1999 only - Feb 21 0:00 0 -
+# Decree <a href="http://pcdsh01.on.br/figuras/HV3150.gif">3,150</a>
+# (1999-08-23) adopted by same states.
+# Decree <a href="http://pcdsh01.on.br/DecHV99.gif">3,188</a> (1999-09-30)
+# adds SE, AL, PB, PE, RN, CE, PI, MA and RR.
+Rule Brazil 1999 only - Oct 3 0:00 1:00 S
+Rule Brazil 2000 only - Feb 27 0:00 0 -
+# Decree <a href="http://pcdsh01.on.br/DEC3592.htm">3,592</a> (2000-09-06)
+# adopted by the same states as before.
+# Decree <a href="http://pcdsh01.on.br/Dec3630.jpg">3,630</a> (2000-10-13)
+# repeals DST in PE and RR, effective 2000-10-15 00:00.
+# Decree <a href="http://pcdsh01.on.br/Dec3632.jpg">3,632</a> (2000-10-17)
+# repeals DST in SE, AL, PB, RN, CE, PI and MA, effective 2000-10-22 00:00.
+# Decree <a href="http://pcdsh01.on.br/figuras/HV3916.gif">3,916</a>
+# (2001-09-13) reestablishes DST in AL, CE, MA, PB, PE, PI, RN, SE.
+Rule Brazil 2000 2001 - Oct Sun>=8 0:00 1:00 S
+Rule Brazil 2001 2006 - Feb Sun>=15 0:00 0 -
+# Decree 4,399 (2002-10-01) repeals DST in AL, CE, MA, PB, PE, PI, RN, SE.
+# <a href="http://www.presidencia.gov.br/CCIVIL/decreto/2002/D4399.htm">4,399</a>
+Rule Brazil 2002 only - Nov 3 0:00 1:00 S
+# Decree 4,844 (2003-09-24; corrected 2003-09-26) repeals DST in BA, MT, TO.
+# <a href="http://www.presidencia.gov.br/CCIVIL/decreto/2003/D4844.htm">4,844</a>
+Rule Brazil 2003 only - Oct 19 0:00 1:00 S
+# Decree 5,223 (2004-10-01) reestablishes DST in MT.
+# <a href="http://www.planalto.gov.br/ccivil_03/_Ato2004-2006/2004/Decreto/D5223.htm">5,223</a>
+Rule Brazil 2004 only - Nov 2 0:00 1:00 S
+# Decree <a href="http://pcdsh01.on.br/DecHV5539.gif">5,539</a> (2005-09-19),
+# adopted by the same states as before.
+Rule Brazil 2005 only - Oct 16 0:00 1:00 S
+# Decree <a href="http://pcdsh01.on.br/DecHV5920.gif">5,920</a> (2006-10-03),
+# adopted by the same states as before.
+Rule Brazil 2006 only - Nov 5 0:00 1:00 S
+Rule Brazil 2007 only - Feb 25 0:00 0 -
+# Decree <a href="http://pcdsh01.on.br/DecHV6212.gif">6,212</a> (2007-09-26),
+# adopted by the same states as before.
+Rule Brazil 2007 only - Oct Sun>=8 0:00 1:00 S
+# From Frederico A. C. Neves (2008-09-10):
+# Acording to this decree
+# <a href="http://www.planalto.gov.br/ccivil_03/_Ato2007-2010/2008/Decreto/D6558.htm">
+# http://www.planalto.gov.br/ccivil_03/_Ato2007-2010/2008/Decreto/D6558.htm
+# </a>
+# [t]he DST period in Brazil now on will be from the 3rd Oct Sunday to the
+# 3rd Feb Sunday. There is an exception on the return date when this is
+# the Carnival Sunday then the return date will be the next Sunday...
+Rule Brazil 2008 max - Oct Sun>=15 0:00 1:00 S
+Rule Brazil 2008 2011 - Feb Sun>=15 0:00 0 -
+Rule Brazil 2012 only - Feb Sun>=22 0:00 0 -
+Rule Brazil 2013 2014 - Feb Sun>=15 0:00 0 -
+Rule Brazil 2015 only - Feb Sun>=22 0:00 0 -
+Rule Brazil 2016 2022 - Feb Sun>=15 0:00 0 -
+Rule Brazil 2023 only - Feb Sun>=22 0:00 0 -
+Rule Brazil 2024 2025 - Feb Sun>=15 0:00 0 -
+Rule Brazil 2026 only - Feb Sun>=22 0:00 0 -
+Rule Brazil 2027 2033 - Feb Sun>=15 0:00 0 -
+Rule Brazil 2034 only - Feb Sun>=22 0:00 0 -
+Rule Brazil 2035 2036 - Feb Sun>=15 0:00 0 -
+Rule Brazil 2037 only - Feb Sun>=22 0:00 0 -
+# From Arthur David Olson (2008-09-29):
+# The next is wrong in some years but is better than nothing.
+Rule Brazil 2038 max - Feb Sun>=15 0:00 0 -
+
+# The latest ruleset listed above says that the following states observe DST:
+# DF, ES, GO, MG, MS, MT, PR, RJ, RS, SC, SP.
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+#
+# Fernando de Noronha (administratively part of PE)
+Zone America/Noronha -2:09:40 - LMT 1914
+ -2:00 Brazil FN%sT 1990 Sep 17
+ -2:00 - FNT 1999 Sep 30
+ -2:00 Brazil FN%sT 2000 Oct 15
+ -2:00 - FNT 2001 Sep 13
+ -2:00 Brazil FN%sT 2002 Oct 1
+ -2:00 - FNT
+# Other Atlantic islands have no permanent settlement.
+# These include Trindade and Martin Vaz (administratively part of ES),
+# Atol das Rocas (RN), and Penedos de Sao Pedro e Sao Paulo (PE).
+# Fernando de Noronha was a separate territory from 1942-09-02 to 1989-01-01;
+# it also included the Penedos.
+#
+# Amapa (AP), east Para (PA)
+# East Para includes Belem, Maraba, Serra Norte, and Sao Felix do Xingu.
+# The division between east and west Para is the river Xingu.
+# In the north a very small part from the river Javary (now Jari I guess,
+# the border with Amapa) to the Amazon, then to the Xingu.
+Zone America/Belem -3:13:56 - LMT 1914
+ -3:00 Brazil BR%sT 1988 Sep 12
+ -3:00 - BRT
+#
+# west Para (PA)
+# West Para includes Altamira, Oribidos, Prainha, Oriximina, and Santarem.
+Zone America/Santarem -3:38:48 - LMT 1914
+ -4:00 Brazil AM%sT 1988 Sep 12
+ -4:00 - AMT 2008 Jun 24 00:00
+ -3:00 - BRT
+#
+# Maranhao (MA), Piaui (PI), Ceara (CE), Rio Grande do Norte (RN),
+# Paraiba (PB)
+Zone America/Fortaleza -2:34:00 - LMT 1914
+ -3:00 Brazil BR%sT 1990 Sep 17
+ -3:00 - BRT 1999 Sep 30
+ -3:00 Brazil BR%sT 2000 Oct 22
+ -3:00 - BRT 2001 Sep 13
+ -3:00 Brazil BR%sT 2002 Oct 1
+ -3:00 - BRT
+#
+# Pernambuco (PE) (except Atlantic islands)
+Zone America/Recife -2:19:36 - LMT 1914
+ -3:00 Brazil BR%sT 1990 Sep 17
+ -3:00 - BRT 1999 Sep 30
+ -3:00 Brazil BR%sT 2000 Oct 15
+ -3:00 - BRT 2001 Sep 13
+ -3:00 Brazil BR%sT 2002 Oct 1
+ -3:00 - BRT
+#
+# Tocantins (TO)
+Zone America/Araguaina -3:12:48 - LMT 1914
+ -3:00 Brazil BR%sT 1990 Sep 17
+ -3:00 - BRT 1995 Sep 14
+ -3:00 Brazil BR%sT 2003 Sep 24
+ -3:00 - BRT
+#
+# Alagoas (AL), Sergipe (SE)
+Zone America/Maceio -2:22:52 - LMT 1914
+ -3:00 Brazil BR%sT 1990 Sep 17
+ -3:00 - BRT 1995 Oct 13
+ -3:00 Brazil BR%sT 1996 Sep 4
+ -3:00 - BRT 1999 Sep 30
+ -3:00 Brazil BR%sT 2000 Oct 22
+ -3:00 - BRT 2001 Sep 13
+ -3:00 Brazil BR%sT 2002 Oct 1
+ -3:00 - BRT
+#
+# Bahia (BA)
+# There are too many Salvadors elsewhere, so use America/Bahia instead
+# of America/Salvador.
+Zone America/Bahia -2:34:04 - LMT 1914
+ -3:00 Brazil BR%sT 2003 Sep 24
+ -3:00 - BRT
+#
+# Goias (GO), Distrito Federal (DF), Minas Gerais (MG),
+# Espirito Santo (ES), Rio de Janeiro (RJ), Sao Paulo (SP), Parana (PR),
+# Santa Catarina (SC), Rio Grande do Sul (RS)
+Zone America/Sao_Paulo -3:06:28 - LMT 1914
+ -3:00 Brazil BR%sT 1963 Oct 23 00:00
+ -3:00 1:00 BRST 1964
+ -3:00 Brazil BR%sT
+#
+# Mato Grosso do Sul (MS)
+Zone America/Campo_Grande -3:38:28 - LMT 1914
+ -4:00 Brazil AM%sT
+#
+# Mato Grosso (MT)
+Zone America/Cuiaba -3:44:20 - LMT 1914
+ -4:00 Brazil AM%sT 2003 Sep 24
+ -4:00 - AMT 2004 Oct 1
+ -4:00 Brazil AM%sT
+#
+# Rondonia (RO)
+Zone America/Porto_Velho -4:15:36 - LMT 1914
+ -4:00 Brazil AM%sT 1988 Sep 12
+ -4:00 - AMT
+#
+# Roraima (RR)
+Zone America/Boa_Vista -4:02:40 - LMT 1914
+ -4:00 Brazil AM%sT 1988 Sep 12
+ -4:00 - AMT 1999 Sep 30
+ -4:00 Brazil AM%sT 2000 Oct 15
+ -4:00 - AMT
+#
+# east Amazonas (AM): Boca do Acre, Jutai, Manaus, Floriano Peixoto
+# The great circle line from Tabatinga to Porto Acre divides
+# east from west Amazonas.
+Zone America/Manaus -4:00:04 - LMT 1914
+ -4:00 Brazil AM%sT 1988 Sep 12
+ -4:00 - AMT 1993 Sep 28
+ -4:00 Brazil AM%sT 1994 Sep 22
+ -4:00 - AMT
+#
+# west Amazonas (AM): Atalaia do Norte, Boca do Maoco, Benjamin Constant,
+# Eirunepe, Envira, Ipixuna
+Zone America/Eirunepe -4:39:28 - LMT 1914
+ -5:00 Brazil AC%sT 1988 Sep 12
+ -5:00 - ACT 1993 Sep 28
+ -5:00 Brazil AC%sT 1994 Sep 22
+ -5:00 - ACT 2008 Jun 24 00:00
+ -4:00 - AMT
+#
+# Acre (AC)
+Zone America/Rio_Branco -4:31:12 - LMT 1914
+ -5:00 Brazil AC%sT 1988 Sep 12
+ -5:00 - ACT 2008 Jun 24 00:00
+ -4:00 - AMT
+
+# Chile
+
+# From Eduardo Krell (1995-10-19):
+# The law says to switch to DST at midnight [24:00] on the second SATURDAY
+# of October.... The law is the same for March and October.
+# (1998-09-29):
+# Because of the drought this year, the government decided to go into
+# DST earlier (saturday 9/26 at 24:00). This is a one-time change only ...
+# (unless there's another dry season next year, I guess).
+
+# From Julio I. Pacheco Troncoso (1999-03-18):
+# Because of the same drought, the government decided to end DST later,
+# on April 3, (one-time change).
+
+# From Oscar van Vlijmen (2006-10-08):
+# http://www.horaoficial.cl/cambio.htm
+
+# From Jesper Norgaard Welen (2006-10-08):
+# I think that there are some obvious mistakes in the suggested link
+# from Oscar van Vlijmen,... for instance entry 66 says that GMT-4
+# ended 1990-09-12 while entry 67 only begins GMT-3 at 1990-09-15
+# (they should have been 1990-09-15 and 1990-09-16 respectively), but
+# anyhow it clears up some doubts too.
+
+# From Paul Eggert (2006-12-27):
+# The following data for Chile and America/Santiago are from
+# <http://www.horaoficial.cl/horaof.htm> (2006-09-20), transcribed by
+# Jesper Norgaard Welen. The data for Pacific/Easter are from Shanks
+# & Pottenger, except with DST transitions after 1932 cloned from
+# America/Santiago. The pre-1980 Pacific/Easter data are dubious,
+# but we have no other source.
+
+# From German Poo-Caaman~o (2008-03-03):
+# Due to drought, Chile extends Daylight Time in three weeks. This
+# is one-time change (Saturday 3/29 at 24:00 for America/Santiago
+# and Saturday 3/29 at 22:00 for Pacific/Easter)
+# The Supreme Decree is located at
+# <a href="http://www.shoa.cl/servicios/supremo316.pdf">
+# http://www.shoa.cl/servicios/supremo316.pdf
+# </a>
+# and the instructions for 2008 are located in:
+# <a href="http://www.horaoficial.cl/cambio.htm">
+# http://www.horaoficial.cl/cambio.htm
+# </a>.
+
+# From Jose Miguel Garrido (2008-03-05):
+# ...
+# You could see the announces of the change on
+# <a href="http://www.shoa.cl/noticias/2008/04hora/hora.htm">
+# http://www.shoa.cl/noticias/2008/04hora/hora.htm
+# </a>.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Chile 1927 1932 - Sep 1 0:00 1:00 S
+Rule Chile 1928 1932 - Apr 1 0:00 0 -
+Rule Chile 1942 only - Jun 1 4:00u 0 -
+Rule Chile 1942 only - Aug 1 5:00u 1:00 S
+Rule Chile 1946 only - Jul 15 4:00u 1:00 S
+Rule Chile 1946 only - Sep 1 3:00u 0:00 -
+Rule Chile 1947 only - Apr 1 4:00u 0 -
+Rule Chile 1968 only - Nov 3 4:00u 1:00 S
+Rule Chile 1969 only - Mar 30 3:00u 0 -
+Rule Chile 1969 only - Nov 23 4:00u 1:00 S
+Rule Chile 1970 only - Mar 29 3:00u 0 -
+Rule Chile 1971 only - Mar 14 3:00u 0 -
+Rule Chile 1970 1972 - Oct Sun>=9 4:00u 1:00 S
+Rule Chile 1972 1986 - Mar Sun>=9 3:00u 0 -
+Rule Chile 1973 only - Sep 30 4:00u 1:00 S
+Rule Chile 1974 1987 - Oct Sun>=9 4:00u 1:00 S
+Rule Chile 1987 only - Apr 12 3:00u 0 -
+Rule Chile 1988 1989 - Mar Sun>=9 3:00u 0 -
+Rule Chile 1988 only - Oct Sun>=1 4:00u 1:00 S
+Rule Chile 1989 only - Oct Sun>=9 4:00u 1:00 S
+Rule Chile 1990 only - Mar 18 3:00u 0 -
+Rule Chile 1990 only - Sep 16 4:00u 1:00 S
+Rule Chile 1991 1996 - Mar Sun>=9 3:00u 0 -
+Rule Chile 1991 1997 - Oct Sun>=9 4:00u 1:00 S
+Rule Chile 1997 only - Mar 30 3:00u 0 -
+Rule Chile 1998 only - Mar Sun>=9 3:00u 0 -
+Rule Chile 1998 only - Sep 27 4:00u 1:00 S
+Rule Chile 1999 only - Apr 4 3:00u 0 -
+Rule Chile 1999 max - Oct Sun>=9 4:00u 1:00 S
+Rule Chile 2000 2007 - Mar Sun>=9 3:00u 0 -
+# N.B.: the end of March 29 in Chile is March 30 in Universal time,
+# which is used below in specifying the transition.
+Rule Chile 2008 only - Mar 30 3:00u 0 -
+Rule Chile 2009 max - Mar Sun>=9 3:00u 0 -
+# IATA SSIM anomalies: (1992-02) says 1992-03-14;
+# (1996-09) says 1998-03-08. Ignore these.
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Santiago -4:42:46 - LMT 1890
+ -4:42:46 - SMT 1910 # Santiago Mean Time
+ -5:00 - CLT 1916 Jul 1 # Chile Time
+ -4:42:46 - SMT 1918 Sep 1 # Santiago Mean Time
+ -4:00 - CLT 1919 Jul 1 # Chile Time
+ -4:42:46 - SMT 1927 Sep 1 # Santiago Mean Time
+ -5:00 Chile CL%sT 1947 May 22 # Chile Time
+ -4:00 Chile CL%sT
+Zone Pacific/Easter -7:17:44 - LMT 1890
+ -7:17:28 - EMT 1932 Sep # Easter Mean Time
+ -7:00 Chile EAS%sT 1982 Mar 13 21:00 # Easter I Time
+ -6:00 Chile EAS%sT
+#
+# Sala y Gomez Island is like Pacific/Easter.
+# Other Chilean locations, including Juan Fernandez Is, San Ambrosio,
+# San Felix, and Antarctic bases, are like America/Santiago.
+
+# Colombia
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule CO 1992 only - May 3 0:00 1:00 S
+Rule CO 1993 only - Apr 4 0:00 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Bogota -4:56:20 - LMT 1884 Mar 13
+ -4:56:20 - BMT 1914 Nov 23 # Bogota Mean Time
+ -5:00 CO CO%sT # Colombia Time
+# Malpelo, Providencia, San Andres
+# no information; probably like America/Bogota
+
+# Curacao
+#
+# From Paul Eggert (2006-03-22):
+# Shanks & Pottenger say that The Bottom and Philipsburg have been at
+# -4:00 since standard time was introduced on 1912-03-02; and that
+# Kralendijk and Rincon used Kralendijk Mean Time (-4:33:08) from
+# 1912-02-02 to 1965-01-01. The former is dubious, since S&P also say
+# Saba Island has been like Curacao.
+# This all predates our 1970 cutoff, though.
+#
+# By July 2007 Curacao and St Maarten are planned to become
+# associated states within the Netherlands, much like Aruba;
+# Bonaire, Saba and St Eustatius would become directly part of the
+# Netherlands as Kingdom Islands. This won't affect their time zones
+# though, as far as we know.
+#
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Curacao -4:35:44 - LMT 1912 Feb 12 # Willemstad
+ -4:30 - ANT 1965 # Netherlands Antilles Time
+ -4:00 - AST
+
+# Ecuador
+#
+# From Paul Eggert (2007-03-04):
+# Apparently Ecuador had a failed experiment with DST in 1992.
+# <http://midena.gov.ec/content/view/1261/208/> (2007-02-27) and
+# <http://www.hoy.com.ec/NoticiaNue.asp?row_id=249856> (2006-11-06) both
+# talk about "hora Sixto". Leave this alone for now, as we have no data.
+#
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Guayaquil -5:19:20 - LMT 1890
+ -5:14:00 - QMT 1931 # Quito Mean Time
+ -5:00 - ECT # Ecuador Time
+Zone Pacific/Galapagos -5:58:24 - LMT 1931 # Puerto Baquerizo Moreno
+ -5:00 - ECT 1986
+ -6:00 - GALT # Galapagos Time
+
+# Falklands
+
+# From Paul Eggert (2006-03-22):
+# Between 1990 and 2000 inclusive, Shanks & Pottenger and the IATA agree except
+# the IATA gives 1996-09-08. Go with Shanks & Pottenger.
+
+# From Falkland Islands Government Office, London (2001-01-22)
+# via Jesper Norgaard:
+# ... the clocks revert back to Local Mean Time at 2 am on Sunday 15
+# April 2001 and advance one hour to summer time at 2 am on Sunday 2
+# September. It is anticipated that the clocks will revert back at 2
+# am on Sunday 21 April 2002 and advance to summer time at 2 am on
+# Sunday 1 September.
+
+# From Rives McDow (2001-02-13):
+#
+# I have communicated several times with people there, and the last
+# time I had communications that was helpful was in 1998. Here is
+# what was said then:
+#
+# "The general rule was that Stanley used daylight saving and the Camp
+# did not. However for various reasons many people in the Camp have
+# started to use daylight saving (known locally as 'Stanley Time')
+# There is no rule as to who uses daylight saving - it is a matter of
+# personal choice and so it is impossible to draw a map showing who
+# uses it and who does not. Any list would be out of date as soon as
+# it was produced. This year daylight saving ended on April 18/19th
+# and started again on September 12/13th. I do not know what the rule
+# is, but can find out if you like. We do not change at the same time
+# as UK or Chile."
+#
+# I did have in my notes that the rule was "Second Saturday in Sep at
+# 0:00 until third Saturday in Apr at 0:00". I think that this does
+# not agree in some cases with Shanks; is this true?
+#
+# Also, there is no mention in the list that some areas in the
+# Falklands do not use DST. I have found in my communications there
+# that these areas are on the western half of East Falkland and all of
+# West Falkland. Stanley is the only place that consistently observes
+# DST. Again, as in other places in the world, the farmers don't like
+# it. West Falkland is almost entirely sheep farmers.
+#
+# I know one lady there that keeps a list of which farm keeps DST and
+# which doesn't each year. She runs a shop in Stanley, and says that
+# the list changes each year. She uses it to communicate to her
+# customers, catching them when they are home for lunch or dinner.
+
+# From Paul Eggert (2001-03-05):
+# For now, we'll just record the time in Stanley, since we have no
+# better info.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Falk 1937 1938 - Sep lastSun 0:00 1:00 S
+Rule Falk 1938 1942 - Mar Sun>=19 0:00 0 -
+Rule Falk 1939 only - Oct 1 0:00 1:00 S
+Rule Falk 1940 1942 - Sep lastSun 0:00 1:00 S
+Rule Falk 1943 only - Jan 1 0:00 0 -
+Rule Falk 1983 only - Sep lastSun 0:00 1:00 S
+Rule Falk 1984 1985 - Apr lastSun 0:00 0 -
+Rule Falk 1984 only - Sep 16 0:00 1:00 S
+Rule Falk 1985 2000 - Sep Sun>=9 0:00 1:00 S
+Rule Falk 1986 2000 - Apr Sun>=16 0:00 0 -
+Rule Falk 2001 max - Apr Sun>=15 2:00 0 -
+Rule Falk 2001 max - Sep Sun>=1 2:00 1:00 S
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Atlantic/Stanley -3:51:24 - LMT 1890
+ -3:51:24 - SMT 1912 Mar 12 # Stanley Mean Time
+ -4:00 Falk FK%sT 1983 May # Falkland Is Time
+ -3:00 Falk FK%sT 1985 Sep 15
+ -4:00 Falk FK%sT
+
+# French Guiana
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Cayenne -3:29:20 - LMT 1911 Jul
+ -4:00 - GFT 1967 Oct # French Guiana Time
+ -3:00 - GFT
+
+# Guyana
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Guyana -3:52:40 - LMT 1915 Mar # Georgetown
+ -3:45 - GBGT 1966 May 26 # Br Guiana Time
+ -3:45 - GYT 1975 Jul 31 # Guyana Time
+ -3:00 - GYT 1991
+# IATA SSIM (1996-06) says -4:00. Assume a 1991 switch.
+ -4:00 - GYT
+
+# Paraguay
+# From Paul Eggert (2006-03-22):
+# Shanks & Pottenger say that spring transitions are from 01:00 -> 02:00,
+# and autumn transitions are from 00:00 -> 23:00. Go with pre-1999
+# editions of Shanks, and with the IATA, who say transitions occur at 00:00.
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Para 1975 1988 - Oct 1 0:00 1:00 S
+Rule Para 1975 1978 - Mar 1 0:00 0 -
+Rule Para 1979 1991 - Apr 1 0:00 0 -
+Rule Para 1989 only - Oct 22 0:00 1:00 S
+Rule Para 1990 only - Oct 1 0:00 1:00 S
+Rule Para 1991 only - Oct 6 0:00 1:00 S
+Rule Para 1992 only - Mar 1 0:00 0 -
+Rule Para 1992 only - Oct 5 0:00 1:00 S
+Rule Para 1993 only - Mar 31 0:00 0 -
+Rule Para 1993 1995 - Oct 1 0:00 1:00 S
+Rule Para 1994 1995 - Feb lastSun 0:00 0 -
+Rule Para 1996 only - Mar 1 0:00 0 -
+# IATA SSIM (2000-02) says 1999-10-10; ignore this for now.
+# From Steffen Thorsen (2000-10-02):
+# I have three independent reports that Paraguay changed to DST this Sunday
+# (10-01).
+#
+# Translated by Gwillim Law (2001-02-27) from
+# <a href="http://www.diarionoticias.com.py/011000/nacional/naciona1.htm">
+# Noticias, a daily paper in Asuncion, Paraguay (2000-10-01)
+# </a>:
+# Starting at 0:00 today, the clock will be set forward 60 minutes, in
+# fulfillment of Decree No. 7,273 of the Executive Power.... The time change
+# system has been operating for several years. Formerly there was a separate
+# decree each year; the new law has the same effect, but permanently. Every
+# year, the time will change on the first Sunday of October; likewise, the
+# clock will be set back on the first Sunday of March.
+#
+Rule Para 1996 2001 - Oct Sun>=1 0:00 1:00 S
+# IATA SSIM (1997-09) says Mar 1; go with Shanks & Pottenger.
+Rule Para 1997 only - Feb lastSun 0:00 0 -
+# Shanks & Pottenger say 1999-02-28; IATA SSIM (1999-02) says 1999-02-27, but
+# (1999-09) reports no date; go with above sources and Gerd Knops (2001-02-27).
+Rule Para 1998 2001 - Mar Sun>=1 0:00 0 -
+# From Rives McDow (2002-02-28):
+# A decree was issued in Paraguay (no. 16350) on 2002-02-26 that changed the
+# dst method to be from the first Sunday in September to the first Sunday in
+# April.
+Rule Para 2002 2004 - Apr Sun>=1 0:00 0 -
+Rule Para 2002 2003 - Sep Sun>=1 0:00 1:00 S
+#
+# From Jesper Norgaard Welen (2005-01-02):
+# There are several sources that claim that Paraguay made
+# a timezone rule change in autumn 2004.
+# From Steffen Thorsen (2005-01-05):
+# Decree 1,867 (2004-03-05)
+# From Carlos Raul Perasso via Jesper Norgaard Welen (2006-10-13)
+# <http://www.presidencia.gov.py/decretos/D1867.pdf>
+Rule Para 2004 max - Oct Sun>=15 0:00 1:00 S
+Rule Para 2005 max - Mar Sun>=8 0:00 0 -
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Asuncion -3:50:40 - LMT 1890
+ -3:50:40 - AMT 1931 Oct 10 # Asuncion Mean Time
+ -4:00 - PYT 1972 Oct # Paraguay Time
+ -3:00 - PYT 1974 Apr
+ -4:00 Para PY%sT
+
+# Peru
+#
+# <a href="news:xrGmb.39935$gA1.13896113@news4.srv.hcvlny.cv.net">
+# From Evelyn C. Leeper via Mark Brader (2003-10-26):</a>
+# When we were in Peru in 1985-1986, they apparently switched over
+# sometime between December 29 and January 3 while we were on the Amazon.
+#
+# From Paul Eggert (2006-03-22):
+# Shanks & Pottenger don't have this transition. Assume 1986 was like 1987.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule Peru 1938 only - Jan 1 0:00 1:00 S
+Rule Peru 1938 only - Apr 1 0:00 0 -
+Rule Peru 1938 1939 - Sep lastSun 0:00 1:00 S
+Rule Peru 1939 1940 - Mar Sun>=24 0:00 0 -
+Rule Peru 1986 1987 - Jan 1 0:00 1:00 S
+Rule Peru 1986 1987 - Apr 1 0:00 0 -
+Rule Peru 1990 only - Jan 1 0:00 1:00 S
+Rule Peru 1990 only - Apr 1 0:00 0 -
+# IATA is ambiguous for 1993/1995; go with Shanks & Pottenger.
+Rule Peru 1994 only - Jan 1 0:00 1:00 S
+Rule Peru 1994 only - Apr 1 0:00 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Lima -5:08:12 - LMT 1890
+ -5:08:36 - LMT 1908 Jul 28 # Lima Mean Time?
+ -5:00 Peru PE%sT # Peru Time
+
+# South Georgia
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone Atlantic/South_Georgia -2:26:08 - LMT 1890 # Grytviken
+ -2:00 - GST # South Georgia Time
+
+# South Sandwich Is
+# uninhabited; scientific personnel have wintered
+
+# Suriname
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Paramaribo -3:40:40 - LMT 1911
+ -3:40:52 - PMT 1935 # Paramaribo Mean Time
+ -3:40:36 - PMT 1945 Oct # The capital moved?
+ -3:30 - NEGT 1975 Nov 20 # Dutch Guiana Time
+ -3:30 - SRT 1984 Oct # Suriname Time
+ -3:00 - SRT
+
+# Trinidad and Tobago
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Port_of_Spain -4:06:04 - LMT 1912 Mar 2
+ -4:00 - AST
+
+# Uruguay
+# From Paul Eggert (1993-11-18):
+# Uruguay wins the prize for the strangest peacetime manipulation of the rules.
+# From Shanks & Pottenger:
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+# Whitman gives 1923 Oct 1; go with Shanks & Pottenger.
+Rule Uruguay 1923 only - Oct 2 0:00 0:30 HS
+Rule Uruguay 1924 1926 - Apr 1 0:00 0 -
+Rule Uruguay 1924 1925 - Oct 1 0:00 0:30 HS
+Rule Uruguay 1933 1935 - Oct lastSun 0:00 0:30 HS
+# Shanks & Pottenger give 1935 Apr 1 0:00 & 1936 Mar 30 0:00; go with Whitman.
+Rule Uruguay 1934 1936 - Mar Sat>=25 23:30s 0 -
+Rule Uruguay 1936 only - Nov 1 0:00 0:30 HS
+Rule Uruguay 1937 1941 - Mar lastSun 0:00 0 -
+# Whitman gives 1937 Oct 3; go with Shanks & Pottenger.
+Rule Uruguay 1937 1940 - Oct lastSun 0:00 0:30 HS
+# Whitman gives 1941 Oct 24 - 1942 Mar 27, 1942 Dec 14 - 1943 Apr 13,
+# and 1943 Apr 13 ``to present time''; go with Shanks & Pottenger.
+Rule Uruguay 1941 only - Aug 1 0:00 0:30 HS
+Rule Uruguay 1942 only - Jan 1 0:00 0 -
+Rule Uruguay 1942 only - Dec 14 0:00 1:00 S
+Rule Uruguay 1943 only - Mar 14 0:00 0 -
+Rule Uruguay 1959 only - May 24 0:00 1:00 S
+Rule Uruguay 1959 only - Nov 15 0:00 0 -
+Rule Uruguay 1960 only - Jan 17 0:00 1:00 S
+Rule Uruguay 1960 only - Mar 6 0:00 0 -
+Rule Uruguay 1965 1967 - Apr Sun>=1 0:00 1:00 S
+Rule Uruguay 1965 only - Sep 26 0:00 0 -
+Rule Uruguay 1966 1967 - Oct 31 0:00 0 -
+Rule Uruguay 1968 1970 - May 27 0:00 0:30 HS
+Rule Uruguay 1968 1970 - Dec 2 0:00 0 -
+Rule Uruguay 1972 only - Apr 24 0:00 1:00 S
+Rule Uruguay 1972 only - Aug 15 0:00 0 -
+Rule Uruguay 1974 only - Mar 10 0:00 0:30 HS
+Rule Uruguay 1974 only - Dec 22 0:00 1:00 S
+Rule Uruguay 1976 only - Oct 1 0:00 0 -
+Rule Uruguay 1977 only - Dec 4 0:00 1:00 S
+Rule Uruguay 1978 only - Apr 1 0:00 0 -
+Rule Uruguay 1979 only - Oct 1 0:00 1:00 S
+Rule Uruguay 1980 only - May 1 0:00 0 -
+Rule Uruguay 1987 only - Dec 14 0:00 1:00 S
+Rule Uruguay 1988 only - Mar 14 0:00 0 -
+Rule Uruguay 1988 only - Dec 11 0:00 1:00 S
+Rule Uruguay 1989 only - Mar 12 0:00 0 -
+Rule Uruguay 1989 only - Oct 29 0:00 1:00 S
+# Shanks & Pottenger say no DST was observed in 1990/1 and 1991/2,
+# and that 1992/3's DST was from 10-25 to 03-01. Go with IATA.
+Rule Uruguay 1990 1992 - Mar Sun>=1 0:00 0 -
+Rule Uruguay 1990 1991 - Oct Sun>=21 0:00 1:00 S
+Rule Uruguay 1992 only - Oct 18 0:00 1:00 S
+Rule Uruguay 1993 only - Feb 28 0:00 0 -
+# From Eduardo Cota (2004-09-20):
+# The uruguayan government has decreed a change in the local time....
+# http://www.presidencia.gub.uy/decretos/2004091502.htm
+Rule Uruguay 2004 only - Sep 19 0:00 1:00 S
+# From Steffen Thorsen (2005-03-11):
+# Uruguay's DST was scheduled to end on Sunday, 2005-03-13, but in order to
+# save energy ... it was postponed two weeks....
+# http://www.presidencia.gub.uy/_Web/noticias/2005/03/2005031005.htm
+Rule Uruguay 2005 only - Mar 27 2:00 0 -
+# From Eduardo Cota (2005-09-27):
+# http://www.presidencia.gub.uy/_Web/decretos/2005/09/CM%20119_09%2009%202005_00001.PDF
+# This means that from 2005-10-09 at 02:00 local time, until 2006-03-12 at
+# 02:00 local time, official time in Uruguay will be at GMT -2.
+Rule Uruguay 2005 only - Oct 9 2:00 1:00 S
+Rule Uruguay 2006 only - Mar 12 2:00 0 -
+# From Jesper Norgaard Welen (2006-09-06):
+# http://www.presidencia.gub.uy/_web/decretos/2006/09/CM%20210_08%2006%202006_00001.PDF
+Rule Uruguay 2006 max - Oct Sun>=1 2:00 1:00 S
+Rule Uruguay 2007 max - Mar Sun>=8 2:00 0 -
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Montevideo -3:44:44 - LMT 1898 Jun 28
+ -3:44:44 - MMT 1920 May 1 # Montevideo MT
+ -3:30 Uruguay UY%sT 1942 Dec 14 # Uruguay Time
+ -3:00 Uruguay UY%sT
+
+# Venezuela
+#
+# From John Stainforth (2007-11-28):
+# ... the change for Venezuela originally expected for 2007-12-31 has
+# been brought forward to 2007-12-09. The official announcement was
+# published today in the "Gaceta Oficial de la Republica Bolivariana
+# de Venezuela, numero 38.819" (official document for all laws or
+# resolution publication)
+# http://www.globovision.com/news.php?nid=72208
+
+# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Zone America/Caracas -4:27:44 - LMT 1890
+ -4:27:40 - CMT 1912 Feb 12 # Caracas Mean Time?
+ -4:30 - VET 1965 # Venezuela Time
+ -4:00 - VET 2007 Dec 9 03:00
+ -4:30 - VET
diff --git a/tools/zoneinfo/tzdata2008h/systemv b/tools/zoneinfo/tzdata2008h/systemv
new file mode 100644
index 0000000..6cf9645
--- /dev/null
+++ b/tools/zoneinfo/tzdata2008h/systemv
@@ -0,0 +1,36 @@
+# @(#)systemv 8.1
+
+# Old rules, should the need arise.
+# No attempt is made to handle Newfoundland, since it cannot be expressed
+# using the System V "TZ" scheme (half-hour offset), or anything outside
+# North America (no support for non-standard DST start/end dates), nor
+# the changes in the DST rules in the US after 1976 (which occurred after
+# the old rules were written).
+#
+# If you need the old rules, uncomment ## lines.
+# Compile this *without* leap second correction for true conformance.
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+Rule SystemV min 1973 - Apr lastSun 2:00 1:00 D
+Rule SystemV min 1973 - Oct lastSun 2:00 0 S
+Rule SystemV 1974 only - Jan 6 2:00 1:00 D
+Rule SystemV 1974 only - Nov lastSun 2:00 0 S
+Rule SystemV 1975 only - Feb 23 2:00 1:00 D
+Rule SystemV 1975 only - Oct lastSun 2:00 0 S
+Rule SystemV 1976 max - Apr lastSun 2:00 1:00 D
+Rule SystemV 1976 max - Oct lastSun 2:00 0 S
+
+# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL]
+## Zone SystemV/AST4ADT -4:00 SystemV A%sT
+## Zone SystemV/EST5EDT -5:00 SystemV E%sT
+## Zone SystemV/CST6CDT -6:00 SystemV C%sT
+## Zone SystemV/MST7MDT -7:00 SystemV M%sT
+## Zone SystemV/PST8PDT -8:00 SystemV P%sT
+## Zone SystemV/YST9YDT -9:00 SystemV Y%sT
+## Zone SystemV/AST4 -4:00 - AST
+## Zone SystemV/EST5 -5:00 - EST
+## Zone SystemV/CST6 -6:00 - CST
+## Zone SystemV/MST7 -7:00 - MST
+## Zone SystemV/PST8 -8:00 - PST
+## Zone SystemV/YST9 -9:00 - YST
+## Zone SystemV/HST10 -10:00 - HST
diff --git a/tools/zoneinfo/tzdata2008h/yearistype.sh b/tools/zoneinfo/tzdata2008h/yearistype.sh
new file mode 100644
index 0000000..66dbf89
--- /dev/null
+++ b/tools/zoneinfo/tzdata2008h/yearistype.sh
@@ -0,0 +1,40 @@
+#! /bin/sh
+
+: 'This file is in the public domain, so clarified as of'
+: '2006-07-17 by Arthur David Olson.'
+
+: '@(#)yearistype.sh 8.2'
+
+case $#-$1 in
+ 2-|2-0*|2-*[!0-9]*)
+ echo "$0: wild year - $1" >&2
+ exit 1 ;;
+esac
+
+case $#-$2 in
+ 2-even)
+ case $1 in
+ *[24680]) exit 0 ;;
+ *) exit 1 ;;
+ esac ;;
+ 2-nonpres|2-nonuspres)
+ case $1 in
+ *[02468][048]|*[13579][26]) exit 1 ;;
+ *) exit 0 ;;
+ esac ;;
+ 2-odd)
+ case $1 in
+ *[13579]) exit 0 ;;
+ *) exit 1 ;;
+ esac ;;
+ 2-uspres)
+ case $1 in
+ *[02468][048]|*[13579][26]) exit 0 ;;
+ *) exit 1 ;;
+ esac ;;
+ 2-*)
+ echo "$0: wild type - $2" >&2 ;;
+esac
+
+echo "$0: usage is $0 year even|odd|uspres|nonpres|nonuspres" >&2
+exit 1
diff --git a/tools/zoneinfo/tzdata2008h/zone.tab b/tools/zoneinfo/tzdata2008h/zone.tab
new file mode 100644
index 0000000..ca9c76b
--- /dev/null
+++ b/tools/zoneinfo/tzdata2008h/zone.tab
@@ -0,0 +1,424 @@
+# @(#)zone.tab 8.19
+#
+# TZ zone descriptions
+#
+# From Paul Eggert (1996-08-05):
+#
+# This file contains a table with the following columns:
+# 1. ISO 3166 2-character country code. See the file `iso3166.tab'.
+# 2. Latitude and longitude of the zone's principal location
+# in ISO 6709 sign-degrees-minutes-seconds format,
+# either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS,
+# first latitude (+ is north), then longitude (+ is east).
+# 3. Zone name used in value of TZ environment variable.
+# 4. Comments; present if and only if the country has multiple rows.
+#
+# Columns are separated by a single tab.
+# The table is sorted first by country, then an order within the country that
+# (1) makes some geographical sense, and
+# (2) puts the most populous zones first, where that does not contradict (1).
+#
+# Lines beginning with `#' are comments.
+#
+#country-
+#code coordinates TZ comments
+AD +4230+00131 Europe/Andorra
+AE +2518+05518 Asia/Dubai
+AF +3431+06912 Asia/Kabul
+AG +1703-06148 America/Antigua
+AI +1812-06304 America/Anguilla
+AL +4120+01950 Europe/Tirane
+AM +4011+04430 Asia/Yerevan
+AN +1211-06900 America/Curacao
+AO -0848+01314 Africa/Luanda
+AQ -7750+16636 Antarctica/McMurdo McMurdo Station, Ross Island
+AQ -9000+00000 Antarctica/South_Pole Amundsen-Scott Station, South Pole
+AQ -6734-06808 Antarctica/Rothera Rothera Station, Adelaide Island
+AQ -6448-06406 Antarctica/Palmer Palmer Station, Anvers Island
+AQ -6736+06253 Antarctica/Mawson Mawson Station, Holme Bay
+AQ -6835+07758 Antarctica/Davis Davis Station, Vestfold Hills
+AQ -6617+11031 Antarctica/Casey Casey Station, Bailey Peninsula
+AQ -7824+10654 Antarctica/Vostok Vostok Station, S Magnetic Pole
+AQ -6640+14001 Antarctica/DumontDUrville Dumont-d'Urville Station, Terre Adelie
+AQ -690022+0393524 Antarctica/Syowa Syowa Station, E Ongul I
+AR -3436-05827 America/Argentina/Buenos_Aires Buenos Aires (BA, CF)
+AR -3124-06411 America/Argentina/Cordoba most locations (CB, CC, CN, ER, FM, LP, MN, NQ, RN, SA, SE, SF)
+AR -3319-06621 America/Argentina/San_Luis San Luis (SL)
+AR -2411-06518 America/Argentina/Jujuy Jujuy (JY)
+AR -2649-06513 America/Argentina/Tucuman Tucuman (TM)
+AR -2828-06547 America/Argentina/Catamarca Catamarca (CT), Chubut (CH)
+AR -2926-06651 America/Argentina/La_Rioja La Rioja (LR)
+AR -3132-06831 America/Argentina/San_Juan San Juan (SJ)
+AR -3253-06849 America/Argentina/Mendoza Mendoza (MZ)
+AR -5138-06913 America/Argentina/Rio_Gallegos Santa Cruz (SC)
+AR -5448-06818 America/Argentina/Ushuaia Tierra del Fuego (TF)
+AS -1416-17042 Pacific/Pago_Pago
+AT +4813+01620 Europe/Vienna
+AU -3133+15905 Australia/Lord_Howe Lord Howe Island
+AU -4253+14719 Australia/Hobart Tasmania - most locations
+AU -3956+14352 Australia/Currie Tasmania - King Island
+AU -3749+14458 Australia/Melbourne Victoria
+AU -3352+15113 Australia/Sydney New South Wales - most locations
+AU -3157+14127 Australia/Broken_Hill New South Wales - Yancowinna
+AU -2728+15302 Australia/Brisbane Queensland - most locations
+AU -2016+14900 Australia/Lindeman Queensland - Holiday Islands
+AU -3455+13835 Australia/Adelaide South Australia
+AU -1228+13050 Australia/Darwin Northern Territory
+AU -3157+11551 Australia/Perth Western Australia - most locations
+AU -3143+12852 Australia/Eucla Western Australia - Eucla area
+AW +1230-06958 America/Aruba
+AX +6006+01957 Europe/Mariehamn
+AZ +4023+04951 Asia/Baku
+BA +4352+01825 Europe/Sarajevo
+BB +1306-05937 America/Barbados
+BD +2343+09025 Asia/Dhaka
+BE +5050+00420 Europe/Brussels
+BF +1222-00131 Africa/Ouagadougou
+BG +4241+02319 Europe/Sofia
+BH +2623+05035 Asia/Bahrain
+BI -0323+02922 Africa/Bujumbura
+BJ +0629+00237 Africa/Porto-Novo
+BL +1753-06251 America/St_Barthelemy
+BM +3217-06446 Atlantic/Bermuda
+BN +0456+11455 Asia/Brunei
+BO -1630-06809 America/La_Paz
+BR -0351-03225 America/Noronha Atlantic islands
+BR -0127-04829 America/Belem Amapa, E Para
+BR -0343-03830 America/Fortaleza NE Brazil (MA, PI, CE, RN, PB)
+BR -0803-03454 America/Recife Pernambuco
+BR -0712-04812 America/Araguaina Tocantins
+BR -0940-03543 America/Maceio Alagoas, Sergipe
+BR -1259-03831 America/Bahia Bahia
+BR -2332-04637 America/Sao_Paulo S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)
+BR -2027-05437 America/Campo_Grande Mato Grosso do Sul
+BR -1535-05605 America/Cuiaba Mato Grosso
+BR -0226-05452 America/Santarem W Para
+BR -0846-06354 America/Porto_Velho Rondonia
+BR +0249-06040 America/Boa_Vista Roraima
+BR -0308-06001 America/Manaus E Amazonas
+BR -0640-06952 America/Eirunepe W Amazonas
+BR -0958-06748 America/Rio_Branco Acre
+BS +2505-07721 America/Nassau
+BT +2728+08939 Asia/Thimphu
+BW -2545+02555 Africa/Gaborone
+BY +5354+02734 Europe/Minsk
+BZ +1730-08812 America/Belize
+CA +4734-05243 America/St_Johns Newfoundland Time, including SE Labrador
+CA +4439-06336 America/Halifax Atlantic Time - Nova Scotia (most places), PEI
+CA +4612-05957 America/Glace_Bay Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971
+CA +4606-06447 America/Moncton Atlantic Time - New Brunswick
+CA +5320-06025 America/Goose_Bay Atlantic Time - Labrador - most locations
+CA +5125-05707 America/Blanc-Sablon Atlantic Standard Time - Quebec - Lower North Shore
+CA +4531-07334 America/Montreal Eastern Time - Quebec - most locations
+CA +4339-07923 America/Toronto Eastern Time - Ontario - most locations
+CA +4901-08816 America/Nipigon Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973
+CA +4823-08915 America/Thunder_Bay Eastern Time - Thunder Bay, Ontario
+CA +6344-06828 America/Iqaluit Eastern Time - east Nunavut - most locations
+CA +6608-06544 America/Pangnirtung Eastern Time - Pangnirtung, Nunavut
+CA +744144-0944945 America/Resolute Eastern Time - Resolute, Nunavut
+CA +484531-0913718 America/Atikokan Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut
+CA +624900-0920459 America/Rankin_Inlet Central Time - central Nunavut
+CA +4953-09709 America/Winnipeg Central Time - Manitoba & west Ontario
+CA +4843-09434 America/Rainy_River Central Time - Rainy River & Fort Frances, Ontario
+CA +5024-10439 America/Regina Central Standard Time - Saskatchewan - most locations
+CA +5017-10750 America/Swift_Current Central Standard Time - Saskatchewan - midwest
+CA +5333-11328 America/Edmonton Mountain Time - Alberta, east British Columbia & west Saskatchewan
+CA +690650-1050310 America/Cambridge_Bay Mountain Time - west Nunavut
+CA +6227-11421 America/Yellowknife Mountain Time - central Northwest Territories
+CA +682059-1334300 America/Inuvik Mountain Time - west Northwest Territories
+CA +5946-12014 America/Dawson_Creek Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia
+CA +4916-12307 America/Vancouver Pacific Time - west British Columbia
+CA +6043-13503 America/Whitehorse Pacific Time - south Yukon
+CA +6404-13925 America/Dawson Pacific Time - north Yukon
+CC -1210+09655 Indian/Cocos
+CD -0418+01518 Africa/Kinshasa west Dem. Rep. of Congo
+CD -1140+02728 Africa/Lubumbashi east Dem. Rep. of Congo
+CF +0422+01835 Africa/Bangui
+CG -0416+01517 Africa/Brazzaville
+CH +4723+00832 Europe/Zurich
+CI +0519-00402 Africa/Abidjan
+CK -2114-15946 Pacific/Rarotonga
+CL -3327-07040 America/Santiago most locations
+CL -2709-10926 Pacific/Easter Easter Island & Sala y Gomez
+CM +0403+00942 Africa/Douala
+CN +3114+12128 Asia/Shanghai east China - Beijing, Guangdong, Shanghai, etc.
+CN +4545+12641 Asia/Harbin Heilongjiang (except Mohe), Jilin
+CN +2934+10635 Asia/Chongqing central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc.
+CN +4348+08735 Asia/Urumqi most of Tibet & Xinjiang
+CN +3929+07559 Asia/Kashgar west Tibet & Xinjiang
+CO +0436-07405 America/Bogota
+CR +0956-08405 America/Costa_Rica
+CU +2308-08222 America/Havana
+CV +1455-02331 Atlantic/Cape_Verde
+CX -1025+10543 Indian/Christmas
+CY +3510+03322 Asia/Nicosia
+CZ +5005+01426 Europe/Prague
+DE +5230+01322 Europe/Berlin
+DJ +1136+04309 Africa/Djibouti
+DK +5540+01235 Europe/Copenhagen
+DM +1518-06124 America/Dominica
+DO +1828-06954 America/Santo_Domingo
+DZ +3647+00303 Africa/Algiers
+EC -0210-07950 America/Guayaquil mainland
+EC -0054-08936 Pacific/Galapagos Galapagos Islands
+EE +5925+02445 Europe/Tallinn
+EG +3003+03115 Africa/Cairo
+EH +2709-01312 Africa/El_Aaiun
+ER +1520+03853 Africa/Asmara
+ES +4024-00341 Europe/Madrid mainland
+ES +3553-00519 Africa/Ceuta Ceuta & Melilla
+ES +2806-01524 Atlantic/Canary Canary Islands
+ET +0902+03842 Africa/Addis_Ababa
+FI +6010+02458 Europe/Helsinki
+FJ -1808+17825 Pacific/Fiji
+FK -5142-05751 Atlantic/Stanley
+FM +0725+15147 Pacific/Truk Truk (Chuuk) and Yap
+FM +0658+15813 Pacific/Ponape Ponape (Pohnpei)
+FM +0519+16259 Pacific/Kosrae Kosrae
+FO +6201-00646 Atlantic/Faroe
+FR +4852+00220 Europe/Paris
+GA +0023+00927 Africa/Libreville
+GB +513030-0000731 Europe/London
+GD +1203-06145 America/Grenada
+GE +4143+04449 Asia/Tbilisi
+GF +0456-05220 America/Cayenne
+GG +4927-00232 Europe/Guernsey
+GH +0533-00013 Africa/Accra
+GI +3608-00521 Europe/Gibraltar
+GL +6411-05144 America/Godthab most locations
+GL +7646-01840 America/Danmarkshavn east coast, north of Scoresbysund
+GL +7029-02158 America/Scoresbysund Scoresbysund / Ittoqqortoormiit
+GL +7634-06847 America/Thule Thule / Pituffik
+GM +1328-01639 Africa/Banjul
+GN +0931-01343 Africa/Conakry
+GP +1614-06132 America/Guadeloupe
+GQ +0345+00847 Africa/Malabo
+GR +3758+02343 Europe/Athens
+GS -5416-03632 Atlantic/South_Georgia
+GT +1438-09031 America/Guatemala
+GU +1328+14445 Pacific/Guam
+GW +1151-01535 Africa/Bissau
+GY +0648-05810 America/Guyana
+HK +2217+11409 Asia/Hong_Kong
+HN +1406-08713 America/Tegucigalpa
+HR +4548+01558 Europe/Zagreb
+HT +1832-07220 America/Port-au-Prince
+HU +4730+01905 Europe/Budapest
+ID -0610+10648 Asia/Jakarta Java & Sumatra
+ID -0002+10920 Asia/Pontianak west & central Borneo
+ID -0507+11924 Asia/Makassar east & south Borneo, Celebes, Bali, Nusa Tengarra, west Timor
+ID -0232+14042 Asia/Jayapura Irian Jaya & the Moluccas
+IE +5320-00615 Europe/Dublin
+IL +3146+03514 Asia/Jerusalem
+IM +5409-00428 Europe/Isle_of_Man
+IN +2232+08822 Asia/Kolkata
+IO -0720+07225 Indian/Chagos
+IQ +3321+04425 Asia/Baghdad
+IR +3540+05126 Asia/Tehran
+IS +6409-02151 Atlantic/Reykjavik
+IT +4154+01229 Europe/Rome
+JE +4912-00207 Europe/Jersey
+JM +1800-07648 America/Jamaica
+JO +3157+03556 Asia/Amman
+JP +353916+1394441 Asia/Tokyo
+KE -0117+03649 Africa/Nairobi
+KG +4254+07436 Asia/Bishkek
+KH +1133+10455 Asia/Phnom_Penh
+KI +0125+17300 Pacific/Tarawa Gilbert Islands
+KI -0308-17105 Pacific/Enderbury Phoenix Islands
+KI +0152-15720 Pacific/Kiritimati Line Islands
+KM -1141+04316 Indian/Comoro
+KN +1718-06243 America/St_Kitts
+KP +3901+12545 Asia/Pyongyang
+KR +3733+12658 Asia/Seoul
+KW +2920+04759 Asia/Kuwait
+KY +1918-08123 America/Cayman
+KZ +4315+07657 Asia/Almaty most locations
+KZ +4448+06528 Asia/Qyzylorda Qyzylorda (Kyzylorda, Kzyl-Orda)
+KZ +5017+05710 Asia/Aqtobe Aqtobe (Aktobe)
+KZ +4431+05016 Asia/Aqtau Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)
+KZ +5113+05121 Asia/Oral West Kazakhstan
+LA +1758+10236 Asia/Vientiane
+LB +3353+03530 Asia/Beirut
+LC +1401-06100 America/St_Lucia
+LI +4709+00931 Europe/Vaduz
+LK +0656+07951 Asia/Colombo
+LR +0618-01047 Africa/Monrovia
+LS -2928+02730 Africa/Maseru
+LT +5441+02519 Europe/Vilnius
+LU +4936+00609 Europe/Luxembourg
+LV +5657+02406 Europe/Riga
+LY +3254+01311 Africa/Tripoli
+MA +3339-00735 Africa/Casablanca
+MC +4342+00723 Europe/Monaco
+MD +4700+02850 Europe/Chisinau
+ME +4226+01916 Europe/Podgorica
+MF +1804-06305 America/Marigot
+MG -1855+04731 Indian/Antananarivo
+MH +0709+17112 Pacific/Majuro most locations
+MH +0905+16720 Pacific/Kwajalein Kwajalein
+MK +4159+02126 Europe/Skopje
+ML +1239-00800 Africa/Bamako
+MM +1647+09610 Asia/Rangoon
+MN +4755+10653 Asia/Ulaanbaatar most locations
+MN +4801+09139 Asia/Hovd Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan
+MN +4804+11430 Asia/Choibalsan Dornod, Sukhbaatar
+MO +2214+11335 Asia/Macau
+MP +1512+14545 Pacific/Saipan
+MQ +1436-06105 America/Martinique
+MR +1806-01557 Africa/Nouakchott
+MS +1643-06213 America/Montserrat
+MT +3554+01431 Europe/Malta
+MU -2010+05730 Indian/Mauritius
+MV +0410+07330 Indian/Maldives
+MW -1547+03500 Africa/Blantyre
+MX +1924-09909 America/Mexico_City Central Time - most locations
+MX +2105-08646 America/Cancun Central Time - Quintana Roo
+MX +2058-08937 America/Merida Central Time - Campeche, Yucatan
+MX +2540-10019 America/Monterrey Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas
+MX +2313-10625 America/Mazatlan Mountain Time - S Baja, Nayarit, Sinaloa
+MX +2838-10605 America/Chihuahua Mountain Time - Chihuahua
+MX +2904-11058 America/Hermosillo Mountain Standard Time - Sonora
+MX +3232-11701 America/Tijuana Pacific Time
+MY +0310+10142 Asia/Kuala_Lumpur peninsular Malaysia
+MY +0133+11020 Asia/Kuching Sabah & Sarawak
+MZ -2558+03235 Africa/Maputo
+NA -2234+01706 Africa/Windhoek
+NC -2216+16530 Pacific/Noumea
+NE +1331+00207 Africa/Niamey
+NF -2903+16758 Pacific/Norfolk
+NG +0627+00324 Africa/Lagos
+NI +1209-08617 America/Managua
+NL +5222+00454 Europe/Amsterdam
+NO +5955+01045 Europe/Oslo
+NP +2743+08519 Asia/Katmandu
+NR -0031+16655 Pacific/Nauru
+NU -1901-16955 Pacific/Niue
+NZ -3652+17446 Pacific/Auckland most locations
+NZ -4357-17633 Pacific/Chatham Chatham Islands
+OM +2336+05835 Asia/Muscat
+PA +0858-07932 America/Panama
+PE -1203-07703 America/Lima
+PF -1732-14934 Pacific/Tahiti Society Islands
+PF -0900-13930 Pacific/Marquesas Marquesas Islands
+PF -2308-13457 Pacific/Gambier Gambier Islands
+PG -0930+14710 Pacific/Port_Moresby
+PH +1435+12100 Asia/Manila
+PK +2452+06703 Asia/Karachi
+PL +5215+02100 Europe/Warsaw
+PM +4703-05620 America/Miquelon
+PN -2504-13005 Pacific/Pitcairn
+PR +182806-0660622 America/Puerto_Rico
+PS +3130+03428 Asia/Gaza
+PT +3843-00908 Europe/Lisbon mainland
+PT +3238-01654 Atlantic/Madeira Madeira Islands
+PT +3744-02540 Atlantic/Azores Azores
+PW +0720+13429 Pacific/Palau
+PY -2516-05740 America/Asuncion
+QA +2517+05132 Asia/Qatar
+RE -2052+05528 Indian/Reunion
+RO +4426+02606 Europe/Bucharest
+RS +4450+02030 Europe/Belgrade
+RU +5443+02030 Europe/Kaliningrad Moscow-01 - Kaliningrad
+RU +5545+03735 Europe/Moscow Moscow+00 - west Russia
+RU +4844+04425 Europe/Volgograd Moscow+00 - Caspian Sea
+RU +5312+05009 Europe/Samara Moscow+01 - Samara, Udmurtia
+RU +5651+06036 Asia/Yekaterinburg Moscow+02 - Urals
+RU +5500+07324 Asia/Omsk Moscow+03 - west Siberia
+RU +5502+08255 Asia/Novosibirsk Moscow+03 - Novosibirsk
+RU +5601+09250 Asia/Krasnoyarsk Moscow+04 - Yenisei River
+RU +5216+10420 Asia/Irkutsk Moscow+05 - Lake Baikal
+RU +6200+12940 Asia/Yakutsk Moscow+06 - Lena River
+RU +4310+13156 Asia/Vladivostok Moscow+07 - Amur River
+RU +4658+14242 Asia/Sakhalin Moscow+07 - Sakhalin Island
+RU +5934+15048 Asia/Magadan Moscow+08 - Magadan
+RU +5301+15839 Asia/Kamchatka Moscow+09 - Kamchatka
+RU +6445+17729 Asia/Anadyr Moscow+10 - Bering Sea
+RW -0157+03004 Africa/Kigali
+SA +2438+04643 Asia/Riyadh
+SB -0932+16012 Pacific/Guadalcanal
+SC -0440+05528 Indian/Mahe
+SD +1536+03232 Africa/Khartoum
+SE +5920+01803 Europe/Stockholm
+SG +0117+10351 Asia/Singapore
+SH -1555-00542 Atlantic/St_Helena
+SI +4603+01431 Europe/Ljubljana
+SJ +7800+01600 Arctic/Longyearbyen
+SK +4809+01707 Europe/Bratislava
+SL +0830-01315 Africa/Freetown
+SM +4355+01228 Europe/San_Marino
+SN +1440-01726 Africa/Dakar
+SO +0204+04522 Africa/Mogadishu
+SR +0550-05510 America/Paramaribo
+ST +0020+00644 Africa/Sao_Tome
+SV +1342-08912 America/El_Salvador
+SY +3330+03618 Asia/Damascus
+SZ -2618+03106 Africa/Mbabane
+TC +2128-07108 America/Grand_Turk
+TD +1207+01503 Africa/Ndjamena
+TF -492110+0701303 Indian/Kerguelen
+TG +0608+00113 Africa/Lome
+TH +1345+10031 Asia/Bangkok
+TJ +3835+06848 Asia/Dushanbe
+TK -0922-17114 Pacific/Fakaofo
+TL -0833+12535 Asia/Dili
+TM +3757+05823 Asia/Ashgabat
+TN +3648+01011 Africa/Tunis
+TO -2110+17510 Pacific/Tongatapu
+TR +4101+02858 Europe/Istanbul
+TT +1039-06131 America/Port_of_Spain
+TV -0831+17913 Pacific/Funafuti
+TW +2503+12130 Asia/Taipei
+TZ -0648+03917 Africa/Dar_es_Salaam
+UA +5026+03031 Europe/Kiev most locations
+UA +4837+02218 Europe/Uzhgorod Ruthenia
+UA +4750+03510 Europe/Zaporozhye Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk
+UA +4457+03406 Europe/Simferopol central Crimea
+UG +0019+03225 Africa/Kampala
+UM +1645-16931 Pacific/Johnston Johnston Atoll
+UM +2813-17722 Pacific/Midway Midway Islands
+UM +1917+16637 Pacific/Wake Wake Island
+US +404251-0740023 America/New_York Eastern Time
+US +421953-0830245 America/Detroit Eastern Time - Michigan - most locations
+US +381515-0854534 America/Kentucky/Louisville Eastern Time - Kentucky - Louisville area
+US +364947-0845057 America/Kentucky/Monticello Eastern Time - Kentucky - Wayne County
+US +394606-0860929 America/Indiana/Indianapolis Eastern Time - Indiana - most locations
+US +384038-0873143 America/Indiana/Vincennes Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties
+US +411745-0863730 America/Indiana/Knox Eastern Time - Indiana - Starke County
+US +410305-0863611 America/Indiana/Winamac Eastern Time - Indiana - Pulaski County
+US +382232-0862041 America/Indiana/Marengo Eastern Time - Indiana - Crawford County
+US +384452-0850402 America/Indiana/Vevay Eastern Time - Indiana - Switzerland County
+US +415100-0873900 America/Chicago Central Time
+US +375711-0864541 America/Indiana/Tell_City Central Time - Indiana - Perry County
+US +382931-0871643 America/Indiana/Petersburg Central Time - Indiana - Pike County
+US +450628-0873651 America/Menominee Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties
+US +470659-1011757 America/North_Dakota/Center Central Time - North Dakota - Oliver County
+US +465042-1012439 America/North_Dakota/New_Salem Central Time - North Dakota - Morton County (except Mandan area)
+US +394421-1045903 America/Denver Mountain Time
+US +433649-1161209 America/Boise Mountain Time - south Idaho & east Oregon
+US +364708-1084111 America/Shiprock Mountain Time - Navajo
+US +332654-1120424 America/Phoenix Mountain Standard Time - Arizona
+US +340308-1181434 America/Los_Angeles Pacific Time
+US +611305-1495401 America/Anchorage Alaska Time
+US +581807-1342511 America/Juneau Alaska Time - Alaska panhandle
+US +593249-1394338 America/Yakutat Alaska Time - Alaska panhandle neck
+US +643004-1652423 America/Nome Alaska Time - west Alaska
+US +515248-1763929 America/Adak Aleutian Islands
+US +211825-1575130 Pacific/Honolulu Hawaii
+UY -3453-05611 America/Montevideo
+UZ +3940+06648 Asia/Samarkand west Uzbekistan
+UZ +4120+06918 Asia/Tashkent east Uzbekistan
+VA +4154+01227 Europe/Vatican
+VC +1309-06114 America/St_Vincent
+VE +1030-06656 America/Caracas
+VG +1827-06437 America/Tortola
+VI +1821-06456 America/St_Thomas
+VN +1045+10640 Asia/Ho_Chi_Minh
+VU -1740+16825 Pacific/Efate
+WF -1318-17610 Pacific/Wallis
+WS -1350-17144 Pacific/Apia
+YE +1245+04512 Asia/Aden
+YT -1247+04514 Indian/Mayotte
+ZA -2615+02800 Africa/Johannesburg
+ZM -1525+02817 Africa/Lusaka
+ZW -1750+03103 Africa/Harare