Browse Source

Write new permissions to the AndroidManifest.xml

Instead of editing the placeholder permissions actually write new ones.
This should solve the privacy statement problems for the Play store.
This means we also no longer need to placeholder permissions in the
template.
Hein-Pieter van Braam 7 years ago
parent
commit
2a126242dd
2 changed files with 106 additions and 200 deletions
  1. 0 165
      platform/android/AndroidManifest.xml.template
  2. 106 35
      platform/android/export/export.cpp

+ 0 - 165
platform/android/AndroidManifest.xml.template

@@ -35,171 +35,6 @@ $$ADD_APPLICATION_CHUNKS$$
     <uses-feature android:glEsVersion="0x00020000" android:required="true" />
     <uses-feature android:glEsVersion="0x00020000" android:required="true" />
 
 
 $$ADD_PERMISSION_CHUNKS$$
 $$ADD_PERMISSION_CHUNKS$$
-<uses-permission android:name="godot.ACCESS_CHECKIN_PROPERTIES"/>
-<uses-permission android:name="godot.ACCESS_COARSE_LOCATION"/>
-<uses-permission android:name="godot.ACCESS_FINE_LOCATION"/>
-<uses-permission android:name="godot.ACCESS_LOCATION_EXTRA_COMMANDS"/>
-<uses-permission android:name="godot.ACCESS_MOCK_LOCATION"/>
-<uses-permission android:name="godot.ACCESS_NETWORK_STATE"/>
-<uses-permission android:name="godot.ACCESS_SURFACE_FLINGER"/>
-<uses-permission android:name="godot.ACCESS_WIFI_STATE"/>
-<uses-permission android:name="godot.ACCOUNT_MANAGER"/>
-<uses-permission android:name="godot.ADD_VOICEMAIL"/>
-<uses-permission android:name="godot.AUTHENTICATE_ACCOUNTS"/>
-<uses-permission android:name="godot.BATTERY_STATS"/>
-<uses-permission android:name="godot.BIND_ACCESSIBILITY_SERVICE"/>
-<uses-permission android:name="godot.BIND_APPWIDGET"/>
-<uses-permission android:name="godot.BIND_DEVICE_ADMIN"/>
-<uses-permission android:name="godot.BIND_INPUT_METHOD"/>
-<uses-permission android:name="godot.BIND_NFC_SERVICE"/>
-<uses-permission android:name="godot.BIND_NOTIFICATION_LISTENER_SERVICE"/>
-<uses-permission android:name="godot.BIND_PRINT_SERVICE"/>
-<uses-permission android:name="godot.BIND_REMOTEVIEWS"/>
-<uses-permission android:name="godot.BIND_TEXT_SERVICE"/>
-<uses-permission android:name="godot.BIND_VPN_SERVICE"/>
-<uses-permission android:name="godot.BIND_WALLPAPER"/>
-<uses-permission android:name="godot.BLUETOOTH"/>
-<uses-permission android:name="godot.BLUETOOTH_ADMIN"/>
-<uses-permission android:name="godot.BLUETOOTH_PRIVILEGED"/>
-<uses-permission android:name="godot.BRICK"/>
-<uses-permission android:name="godot.BROADCAST_PACKAGE_REMOVED"/>
-<uses-permission android:name="godot.BROADCAST_SMS"/>
-<uses-permission android:name="godot.BROADCAST_STICKY"/>
-<uses-permission android:name="godot.BROADCAST_WAP_PUSH"/>
-<uses-permission android:name="godot.CALL_PHONE"/>
-<uses-permission android:name="godot.CALL_PRIVILEGED"/>
-<uses-permission android:name="godot.CAMERA"/>
-<uses-permission android:name="godot.CAPTURE_AUDIO_OUTPUT"/>
-<uses-permission android:name="godot.CAPTURE_SECURE_VIDEO_OUTPUT"/>
-<uses-permission android:name="godot.CAPTURE_VIDEO_OUTPUT"/>
-<uses-permission android:name="godot.CHANGE_COMPONENT_ENABLED_STATE"/>
-<uses-permission android:name="godot.CHANGE_CONFIGURATION"/>
-<uses-permission android:name="godot.CHANGE_NETWORK_STATE"/>
-<uses-permission android:name="godot.CHANGE_WIFI_MULTICAST_STATE"/>
-<uses-permission android:name="godot.CHANGE_WIFI_STATE"/>
-<uses-permission android:name="godot.CLEAR_APP_CACHE"/>
-<uses-permission android:name="godot.CLEAR_APP_USER_DATA"/>
-<uses-permission android:name="godot.CONTROL_LOCATION_UPDATES"/>
-<uses-permission android:name="godot.DELETE_CACHE_FILES"/>
-<uses-permission android:name="godot.DELETE_PACKAGES"/>
-<uses-permission android:name="godot.DEVICE_POWER"/>
-<uses-permission android:name="godot.DIAGNOSTIC"/>
-<uses-permission android:name="godot.DISABLE_KEYGUARD"/>
-<uses-permission android:name="godot.DUMP"/>
-<uses-permission android:name="godot.EXPAND_STATUS_BAR"/>
-<uses-permission android:name="godot.FACTORY_TEST"/>
-<uses-permission android:name="godot.FLASHLIGHT"/>
-<uses-permission android:name="godot.FORCE_BACK"/>
-<uses-permission android:name="godot.GET_ACCOUNTS"/>
-<uses-permission android:name="godot.GET_PACKAGE_SIZE"/>
-<uses-permission android:name="godot.GET_TASKS"/>
-<uses-permission android:name="godot.GET_TOP_ACTIVITY_INFO"/>
-<uses-permission android:name="godot.GLOBAL_SEARCH"/>
-<uses-permission android:name="godot.HARDWARE_TEST"/>
-<uses-permission android:name="godot.INJECT_EVENTS"/>
-<uses-permission android:name="godot.INSTALL_LOCATION_PROVIDER"/>
-<uses-permission android:name="godot.INSTALL_PACKAGES"/>
-<uses-permission android:name="godot.INSTALL_SHORTCUT"/>
-<uses-permission android:name="godot.INTERNAL_SYSTEM_WINDOW"/>
-<uses-permission android:name="godot.INTERNET"/>
-<uses-permission android:name="godot.KILL_BACKGROUND_PROCESSES"/>
-<uses-permission android:name="godot.LOCATION_HARDWARE"/>
-<uses-permission android:name="godot.MANAGE_ACCOUNTS"/>
-<uses-permission android:name="godot.MANAGE_APP_TOKENS"/>
-<uses-permission android:name="godot.MANAGE_DOCUMENTS"/>
-<uses-permission android:name="godot.MASTER_CLEAR"/>
-<uses-permission android:name="godot.MEDIA_CONTENT_CONTROL"/>
-<uses-permission android:name="godot.MODIFY_AUDIO_SETTINGS"/>
-<uses-permission android:name="godot.MODIFY_PHONE_STATE"/>
-<uses-permission android:name="godot.MOUNT_FORMAT_FILESYSTEMS"/>
-<uses-permission android:name="godot.MOUNT_UNMOUNT_FILESYSTEMS"/>
-<uses-permission android:name="godot.NFC"/>
-<uses-permission android:name="godot.PERSISTENT_ACTIVITY"/>
-<uses-permission android:name="godot.PROCESS_OUTGOING_CALLS"/>
-<uses-permission android:name="godot.READ_CALENDAR"/>
-<uses-permission android:name="godot.READ_CALL_LOG"/>
-<uses-permission android:name="godot.READ_CONTACTS"/>
-<uses-permission android:name="godot.READ_EXTERNAL_STORAGE"/>
-<uses-permission android:name="godot.READ_FRAME_BUFFER"/>
-<uses-permission android:name="godot.READ_HISTORY_BOOKMARKS"/>
-<uses-permission android:name="godot.READ_INPUT_STATE"/>
-<uses-permission android:name="godot.READ_LOGS"/>
-<uses-permission android:name="godot.READ_PHONE_STATE"/>
-<uses-permission android:name="godot.READ_PROFILE"/>
-<uses-permission android:name="godot.READ_SMS"/>
-<uses-permission android:name="godot.READ_SOCIAL_STREAM"/>
-<uses-permission android:name="godot.READ_SYNC_SETTINGS"/>
-<uses-permission android:name="godot.READ_SYNC_STATS"/>
-<uses-permission android:name="godot.READ_USER_DICTIONARY"/>
-<uses-permission android:name="godot.REBOOT"/>
-<uses-permission android:name="godot.RECEIVE_BOOT_COMPLETED"/>
-<uses-permission android:name="godot.RECEIVE_MMS"/>
-<uses-permission android:name="godot.RECEIVE_SMS"/>
-<uses-permission android:name="godot.RECEIVE_WAP_PUSH"/>
-<uses-permission android:name="godot.RECORD_AUDIO"/>
-<uses-permission android:name="godot.REORDER_TASKS"/>
-<uses-permission android:name="godot.RESTART_PACKAGES"/>
-<uses-permission android:name="godot.SEND_RESPOND_VIA_MESSAGE"/>
-<uses-permission android:name="godot.SEND_SMS"/>
-<uses-permission android:name="godot.SET_ACTIVITY_WATCHER"/>
-<uses-permission android:name="godot.SET_ALARM"/>
-<uses-permission android:name="godot.SET_ALWAYS_FINISH"/>
-<uses-permission android:name="godot.SET_ANIMATION_SCALE"/>
-<uses-permission android:name="godot.SET_DEBUG_APP"/>
-<uses-permission android:name="godot.SET_ORIENTATION"/>
-<uses-permission android:name="godot.SET_POINTER_SPEED"/>
-<uses-permission android:name="godot.SET_PREFERRED_APPLICATIONS"/>
-<uses-permission android:name="godot.SET_PROCESS_LIMIT"/>
-<uses-permission android:name="godot.SET_TIME"/>
-<uses-permission android:name="godot.SET_TIME_ZONE"/>
-<uses-permission android:name="godot.SET_WALLPAPER"/>
-<uses-permission android:name="godot.SET_WALLPAPER_HINTS"/>
-<uses-permission android:name="godot.SIGNAL_PERSISTENT_PROCESSES"/>
-<uses-permission android:name="godot.STATUS_BAR"/>
-<uses-permission android:name="godot.SUBSCRIBED_FEEDS_READ"/>
-<uses-permission android:name="godot.SUBSCRIBED_FEEDS_WRITE"/>
-<uses-permission android:name="godot.SYSTEM_ALERT_WINDOW"/>
-<uses-permission android:name="godot.TRANSMIT_IR"/>
-<uses-permission android:name="godot.UNINSTALL_SHORTCUT"/>
-<uses-permission android:name="godot.UPDATE_DEVICE_STATS"/>
-<uses-permission android:name="godot.USE_CREDENTIALS"/>
-<uses-permission android:name="godot.USE_SIP"/>
-<uses-permission android:name="godot.VIBRATE"/>
-<uses-permission android:name="godot.WAKE_LOCK"/>
-<uses-permission android:name="godot.WRITE_APN_SETTINGS"/>
-<uses-permission android:name="godot.WRITE_CALENDAR"/>
-<uses-permission android:name="godot.WRITE_CALL_LOG"/>
-<uses-permission android:name="godot.WRITE_CONTACTS"/>
-<uses-permission android:name="godot.WRITE_EXTERNAL_STORAGE"/>
-<uses-permission android:name="godot.WRITE_GSERVICES"/>
-<uses-permission android:name="godot.WRITE_HISTORY_BOOKMARKS"/>
-<uses-permission android:name="godot.WRITE_PROFILE"/>
-<uses-permission android:name="godot.WRITE_SECURE_SETTINGS"/>
-<uses-permission android:name="godot.WRITE_SETTINGS"/>
-<uses-permission android:name="godot.WRITE_SMS"/>
-<uses-permission android:name="godot.WRITE_SOCIAL_STREAM"/>
-<uses-permission android:name="godot.WRITE_SYNC_SETTINGS"/>
-<uses-permission android:name="godot.WRITE_USER_DICTIONARY"/>
-<uses-permission android:name="godot.custom.0"/>
-<uses-permission android:name="godot.custom.1"/>
-<uses-permission android:name="godot.custom.2"/>
-<uses-permission android:name="godot.custom.3"/>
-<uses-permission android:name="godot.custom.4"/>
-<uses-permission android:name="godot.custom.5"/>
-<uses-permission android:name="godot.custom.6"/>
-<uses-permission android:name="godot.custom.7"/>
-<uses-permission android:name="godot.custom.8"/>
-<uses-permission android:name="godot.custom.9"/>
-<uses-permission android:name="godot.custom.10"/>
-<uses-permission android:name="godot.custom.11"/>
-<uses-permission android:name="godot.custom.12"/>
-<uses-permission android:name="godot.custom.13"/>
-<uses-permission android:name="godot.custom.14"/>
-<uses-permission android:name="godot.custom.15"/>
-<uses-permission android:name="godot.custom.16"/>
-<uses-permission android:name="godot.custom.17"/>
-<uses-permission android:name="godot.custom.18"/>
-<uses-permission android:name="godot.custom.19"/>
 
 
 <uses-sdk android:minSdkVersion="18" android:targetSdkVersion="27"/>
 <uses-sdk android:minSdkVersion="18" android:targetSdkVersion="27"/>
 
 

+ 106 - 35
platform/android/export/export.cpp

@@ -570,7 +570,7 @@ class EditorExportAndroid : public EditorExportPlatform {
 		// const int CHUNK_RESOURCEIDS = 0x00080180;
 		// const int CHUNK_RESOURCEIDS = 0x00080180;
 		const int CHUNK_STRINGS = 0x001C0001;
 		const int CHUNK_STRINGS = 0x001C0001;
 		// const int CHUNK_XML_END_NAMESPACE = 0x00100101;
 		// const int CHUNK_XML_END_NAMESPACE = 0x00100101;
-		// const int CHUNK_XML_END_TAG = 0x00100103;
+		const int CHUNK_XML_END_TAG = 0x00100103;
 		// const int CHUNK_XML_START_NAMESPACE = 0x00100100;
 		// const int CHUNK_XML_START_NAMESPACE = 0x00100100;
 		const int CHUNK_XML_START_TAG = 0x00100102;
 		const int CHUNK_XML_START_TAG = 0x00100102;
 		// const int CHUNK_XML_TEXT = 0x00100104;
 		// const int CHUNK_XML_TEXT = 0x00100104;
@@ -601,24 +601,28 @@ class EditorExportAndroid : public EditorExportPlatform {
 		bool screen_support_large = p_preset->get("screen/support_large");
 		bool screen_support_large = p_preset->get("screen/support_large");
 		bool screen_support_xlarge = p_preset->get("screen/support_xlarge");
 		bool screen_support_xlarge = p_preset->get("screen/support_xlarge");
 
 
-		String user_perms[MAX_USER_PERMISSIONS];
-
-		for (int i = 0; i < MAX_USER_PERMISSIONS; i++) {
-
-			user_perms[i] = p_preset->get("user_permissions/" + itos(i));
-		}
-
-		Set<String> perms;
+		Vector<String> perms;
 
 
 		const char **aperms = android_perms;
 		const char **aperms = android_perms;
 		while (*aperms) {
 		while (*aperms) {
 
 
 			bool enabled = p_preset->get("permissions/" + String(*aperms).to_lower());
 			bool enabled = p_preset->get("permissions/" + String(*aperms).to_lower());
 			if (enabled)
 			if (enabled)
-				perms.insert(String(*aperms));
+				perms.push_back("android.permission." + String(*aperms));
 			aperms++;
 			aperms++;
 		}
 		}
 
 
+		for (int i = 0; i < MAX_USER_PERMISSIONS; i++) {
+			String user_perm = p_preset->get("user_permissions/" + itos(i));
+			if (user_perm.strip_edges() != "" && user_perm.strip_edges() != "False")
+				perms.push_back(user_perm.strip_edges());
+		}
+
+		if (p_give_internet) {
+			if (perms.find("android.permission.INTERNET") == -1)
+				perms.push_back("android.permission.INTERNET");
+		}
+
 		while (ofs < (uint32_t)p_manifest.size()) {
 		while (ofs < (uint32_t)p_manifest.size()) {
 
 
 			uint32_t chunk = decode_uint32(&p_manifest[ofs]);
 			uint32_t chunk = decode_uint32(&p_manifest[ofs]);
@@ -741,27 +745,6 @@ class EditorExportAndroid : public EditorExportPlatform {
 							print_line("version number: " + itos(decode_uint32(&p_manifest[iofs + 16])));
 							print_line("version number: " + itos(decode_uint32(&p_manifest[iofs + 16])));
 						}
 						}
 
 
-						if (tname == "uses-permission" && /*nspace=="android" &&*/ attrname == "name") {
-
-							if (value.begins_with("godot.custom")) {
-
-								int which = value.get_slice(".", 2).to_int();
-								if (which >= 0 && which < MAX_USER_PERMISSIONS && user_perms[which].strip_edges() != "") {
-
-									string_table[attr_value] = user_perms[which].strip_edges();
-								}
-
-							} else if (value.begins_with("godot.")) {
-								String perm = value.get_slice(".", 1);
-
-								if (perms.has(perm) || (p_give_internet && perm == "INTERNET")) {
-
-									print_line("PERM: " + perm);
-									string_table[attr_value] = "android.permission." + perm;
-								}
-							}
-						}
-
 						if (tname == "supports-screens") {
 						if (tname == "supports-screens") {
 
 
 							if (attrname == "smallScreens") {
 							if (attrname == "smallScreens") {
@@ -786,6 +769,91 @@ class EditorExportAndroid : public EditorExportPlatform {
 					}
 					}
 
 
 				} break;
 				} break;
+				case CHUNK_XML_END_TAG: {
+					int iofs = ofs + 8;
+					uint32_t name = decode_uint32(&p_manifest[iofs + 12]);
+					String tname = string_table[name];
+
+					if (tname == "manifest") {
+						print_line("Found manifest end");
+
+						// save manifest ending so we can restore it
+						Vector<uint8_t> manifest_end;
+						uint32_t manifest_cur_size = p_manifest.size();
+						uint32_t node_size = size;
+
+						manifest_end.resize(p_manifest.size() - ofs);
+						memcpy(manifest_end.ptrw(), &p_manifest[ofs], manifest_end.size());
+
+						int32_t attr_name_string = string_table.find("name");
+						ERR_EXPLAIN("Template does not have 'name' attribute");
+						ERR_FAIL_COND(attr_name_string == -1);
+
+						int32_t ns_android_string = string_table.find("android");
+						ERR_EXPLAIN("Template does not have 'android' namespace");
+						ERR_FAIL_COND(ns_android_string == -1);
+
+						int32_t attr_uses_permission_string = string_table.find("uses-permission");
+						if (attr_uses_permission_string == -1) {
+							string_table.push_back("uses-permission");
+							attr_uses_permission_string = string_table.size() - 1;
+						}
+
+						for (int i = 0; i < perms.size(); ++i) {
+							print_line("Adding permission " + perms[i]);
+
+							manifest_cur_size += 56 + 24; // node + end node
+							p_manifest.resize(manifest_cur_size);
+
+							// Add permission to the string pool
+							int32_t perm_string = string_table.find(perms[i]);
+							if (perm_string == -1) {
+								string_table.push_back(perms[i]);
+								perm_string = string_table.size() - 1;
+							}
+
+							// start tag
+							encode_uint16(0x102, &p_manifest[ofs]); // type
+							encode_uint16(16, &p_manifest[ofs + 2]); // headersize
+							encode_uint32(56, &p_manifest[ofs + 4]); // size
+							encode_uint32(0, &p_manifest[ofs + 8]); // lineno
+							encode_uint32(-1, &p_manifest[ofs + 12]); // comment
+							encode_uint32(-1, &p_manifest[ofs + 16]); // ns
+							encode_uint32(attr_uses_permission_string, &p_manifest[ofs + 20]); // name
+							encode_uint16(20, &p_manifest[ofs + 24]); // attr_start
+							encode_uint16(20, &p_manifest[ofs + 26]); // attr_size
+							encode_uint16(1, &p_manifest[ofs + 28]); // num_attrs
+							encode_uint16(0, &p_manifest[ofs + 30]); // id_index
+							encode_uint16(0, &p_manifest[ofs + 32]); // class_index
+							encode_uint16(0, &p_manifest[ofs + 34]); // style_index
+
+							// attribute
+							encode_uint32(ns_android_string, &p_manifest[ofs + 36]); // ns
+							encode_uint32(attr_name_string, &p_manifest[ofs + 40]); // 'name'
+							encode_uint32(perm_string, &p_manifest[ofs + 44]); // raw_value
+							encode_uint16(8, &p_manifest[ofs + 48]); // typedvalue_size
+							p_manifest[ofs + 50] = 0; // typedvalue_always0
+							p_manifest[ofs + 51] = 0x03; // typedvalue_type (string)
+							encode_uint32(perm_string, &p_manifest[ofs + 52]); // typedvalue reference
+
+							ofs += 56;
+
+							// end tag
+							encode_uint16(0x103, &p_manifest[ofs]); // type
+							encode_uint16(16, &p_manifest[ofs + 2]); // headersize
+							encode_uint32(24, &p_manifest[ofs + 4]); // size
+							encode_uint32(0, &p_manifest[ofs + 8]); // lineno
+							encode_uint32(-1, &p_manifest[ofs + 12]); // comment
+							encode_uint32(-1, &p_manifest[ofs + 16]); // ns
+							encode_uint32(attr_uses_permission_string, &p_manifest[ofs + 20]); // name
+
+							ofs += 24;
+						}
+
+						// copy footer back in
+						memcpy(&p_manifest[ofs], manifest_end.ptr(), manifest_end.size());
+					}
+				} break;
 			}
 			}
 
 
 			ofs += size;
 			ofs += size;
@@ -806,17 +874,17 @@ class EditorExportAndroid : public EditorExportPlatform {
 
 
 			encode_uint32(ofs, &ret[string_table_begins + i * 4]);
 			encode_uint32(ofs, &ret[string_table_begins + i * 4]);
 			ofs += string_table[i].length() * 2 + 2 + 2;
 			ofs += string_table[i].length() * 2 + 2 + 2;
-			//print_line("ofs: "+itos(i)+": "+itos(ofs));
 		}
 		}
+
 		ret.resize(ret.size() + ofs);
 		ret.resize(ret.size() + ofs);
-		uint8_t *chars = &ret[ret.size() - ofs];
+		string_data_offset = ret.size() - ofs;
+		uint8_t *chars = &ret[string_data_offset];
 		for (int i = 0; i < string_table.size(); i++) {
 		for (int i = 0; i < string_table.size(); i++) {
 
 
 			String s = string_table[i];
 			String s = string_table[i];
-			//print_line("savint string :"+s);
 			encode_uint16(s.length(), chars);
 			encode_uint16(s.length(), chars);
 			chars += 2;
 			chars += 2;
-			for (int j = 0; j < s.length(); j++) { //include zero?
+			for (int j = 0; j < s.length(); j++) {
 				encode_uint16(s[j], chars);
 				encode_uint16(s[j], chars);
 				chars += 2;
 				chars += 2;
 			}
 			}
@@ -828,6 +896,7 @@ class EditorExportAndroid : public EditorExportPlatform {
 			ret.push_back(stable_extra[i]);
 			ret.push_back(stable_extra[i]);
 		}
 		}
 
 
+		//pad
 		while (ret.size() % 4)
 		while (ret.size() % 4)
 			ret.push_back(0);
 			ret.push_back(0);
 
 
@@ -843,6 +912,8 @@ class EditorExportAndroid : public EditorExportPlatform {
 		encode_uint32(ret.size(), &ret[4]); //update new file size
 		encode_uint32(ret.size(), &ret[4]); //update new file size
 
 
 		encode_uint32(new_stable_end - 8, &ret[12]); //update new string table size
 		encode_uint32(new_stable_end - 8, &ret[12]); //update new string table size
+		encode_uint32(string_table.size(), &ret[16]); //update new number of strings
+		encode_uint32(string_data_offset - 8, &ret[28]); //update new string data offset
 
 
 		//print_line("file size: "+itos(ret.size()));
 		//print_line("file size: "+itos(ret.size()));