diff --git a/extern/GmsApi b/extern/GmsApi index 8d39059c..865b4166 160000 --- a/extern/GmsApi +++ b/extern/GmsApi @@ -1 +1 @@ -Subproject commit 8d39059ce60908519a4642562c848d9da063e710 +Subproject commit 865b41664d6afabecddbd1a5d1b7c702d0bd821f diff --git a/extern/UnifiedNlp b/extern/UnifiedNlp index a7755939..3b5727c7 160000 --- a/extern/UnifiedNlp +++ b/extern/UnifiedNlp @@ -1 +1 @@ -Subproject commit a7755939012f931628e623b3cc55b849f5acdf64 +Subproject commit 3b5727c78ab7a997226f2b030d4b168d0b3346a4 diff --git a/libs/vtm-android-0.6.0-SNAPSHOT.aar b/libs/vtm-android-0.6.0-SNAPSHOT.aar index 6c69c2ee..2ab749ee 100644 Binary files a/libs/vtm-android-0.6.0-SNAPSHOT.aar and b/libs/vtm-android-0.6.0-SNAPSHOT.aar differ diff --git a/microg-ui-tools b/microg-ui-tools new file mode 120000 index 00000000..d6e8b594 --- /dev/null +++ b/microg-ui-tools @@ -0,0 +1 @@ +extern/UnifiedNlp/microg-ui-tools/ \ No newline at end of file diff --git a/android_frameworks_base+FAKE_PACKAGE_SIGNATURE.patch b/patches/android_frameworks_base-KK-LP.patch similarity index 100% rename from android_frameworks_base+FAKE_PACKAGE_SIGNATURE.patch rename to patches/android_frameworks_base-KK-LP.patch diff --git a/play-services-core/build.gradle b/play-services-core/build.gradle index 3c3b7dcd..2a580885 100644 --- a/play-services-core/build.gradle +++ b/play-services-core/build.gradle @@ -19,7 +19,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:1.3.0' + classpath 'com.android.tools.build:gradle:1.5.0' } } @@ -33,13 +33,14 @@ repositories { } dependencies { - compile 'com.android.support:support-v4:23.0.1' - compile 'com.android.support:appcompat-v7:23.0.1' compile 'de.hdodenhof:circleimageview:1.2.1' compile 'com.squareup.wire:wire-runtime:1.6.1' + + compile project(":microg-ui-tools") compile project(':play-services-api') compile project(':unifiednlp-base') compile project(':wearable-lib') + // vtm from ./libs compile 'org.oscim:vtm-android:0.6.0-SNAPSHOT@aar' compile 'org.oscim:vtm-themes:0.6.0-SNAPSHOT@jar' @@ -53,10 +54,34 @@ dependencies { compile 'org.slf4j:slf4j-android:1.7.6' } +String getMyVersionName() { + def stdout = new ByteArrayOutputStream() + exec { + commandLine 'git', 'describe', '--tags', '--always', '--dirty' + standardOutput = stdout + } + return stdout.toString().trim() +} + +int getMyVersionCode(String ref) { + def stdout = new ByteArrayOutputStream() + exec { + commandLine 'git', 'rev-list', '--count', "$ref..HEAD" + standardOutput = stdout + } + return Integer.parseInt(stdout.toString().trim()) +} + android { compileSdkVersion 23 buildToolsVersion "23.0.2" + defaultConfig { + versionName("8.4.89 (microG " + getMyVersionName() + ")") + // Update commit id to current when increasing gms version code + versionCode(8489238 + getMyVersionCode('249c935f')) + } + sourceSets { main { java.srcDirs += 'src/main/protos-java' diff --git a/play-services-core/src/main/AndroidManifest.xml b/play-services-core/src/main/AndroidManifest.xml index b01a7f66..6a0922e4 100644 --- a/play-services-core/src/main/AndroidManifest.xml +++ b/play-services-core/src/main/AndroidManifest.xml @@ -14,11 +14,8 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> - + + @@ -78,6 +79,7 @@ + - + android:exported="true"/> @@ -360,11 +361,6 @@ - - infos = getPackageManager().queryBroadcastReceivers(intent, PackageManager.GET_RESOLVED_FILTER); + for (ResolveInfo resolveInfo : infos) + Log.d(TAG, "Target: " + resolveInfo); + if (infos.isEmpty()) + Log.d(TAG, "No target for message, wut?"); sendOrderedBroadcast(intent, msg.category + ".permission.C2D_MESSAGE"); } @@ -308,7 +331,7 @@ public class McsService extends Service implements Handler.Callback { if (inputStream.newStreamIdAvailable()) { msgResponse.last_stream_id_received(inputStream.getStreamId()); } - send(msgResponse.build()); + send(MCS_DATA_MESSAGE_STANZA_TAG, msgResponse.build()); } } } @@ -317,16 +340,16 @@ public class McsService extends Service implements Handler.Callback { return getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE); } - private void send(Message message) { - rootHandler.sendMessage(rootHandler.obtainMessage(MSG_OUTPUT, message)); + private void send(int type, Message message) { + rootHandler.sendMessage(rootHandler.obtainMessage(MSG_OUTPUT, type, 0, message)); } - private void sendOutputStream(int what, Object obj) { + private void sendOutputStream(int what, int arg, Object obj) { McsOutputStream os = outputStream; if (os != null) { Handler outputHandler = os.getHandler(); if (outputHandler != null) - outputHandler.sendMessage(outputHandler.obtainMessage(what, obj)); + outputHandler.sendMessage(outputHandler.obtainMessage(what, arg, 0, obj)); } } @@ -334,10 +357,10 @@ public class McsService extends Service implements Handler.Callback { public boolean handleMessage(android.os.Message msg) { switch (msg.what) { case MSG_INPUT: - handleInput((Message) msg.obj); + handleInput(msg.arg1, (Message) msg.obj); return true; case MSG_OUTPUT: - sendOutputStream(MSG_OUTPUT, msg.obj); + sendOutputStream(MSG_OUTPUT, msg.arg1, msg.obj); return true; case MSG_INPUT_ERROR: case MSG_OUTPUT_ERROR: @@ -361,7 +384,7 @@ public class McsService extends Service implements Handler.Callback { if (inputStream.newStreamIdAvailable()) { ping.last_stream_id_received(inputStream.getStreamId()); } - send(ping.build()); + send(MCS_HEARTBEAT_PING_TAG, ping.build()); scheduleHeartbeat(this); } else { Log.d(TAG, "Ignoring heartbeat, not connected!"); @@ -370,27 +393,45 @@ public class McsService extends Service implements Handler.Callback { return true; case MSG_OUTPUT_READY: Log.d(TAG, "Sending login request..."); - send(buildLoginRequest()); + send(MCS_LOGIN_REQUEST_TAG, buildLoginRequest()); + return true; + case MSG_OUTPUT_DONE: + handleOutputDone(msg); return true; } Log.w(TAG, "Unknown message: " + msg); return false; } - private void handleInput(Message message) { + private void handleOutputDone(android.os.Message msg) { + switch (msg.arg1) { + case MCS_HEARTBEAT_PING_TAG: + wakeLock.release(); + break; + default: + } + } + + private void handleInput(int type, Message message) { try { - if (message instanceof DataMessageStanza) { - handleCloudMessage((DataMessageStanza) message); - } else if (message instanceof HeartbeatPing) { - handleHearbeatPing((HeartbeatPing) message); - } else if (message instanceof Close) { - handleClose((Close) message); - } else if (message instanceof LoginResponse) { - handleLoginResponse((LoginResponse) message); - } else if (message instanceof HeartbeatAck) { - handleHeartbeatAck((HeartbeatAck) message); - } else { - Log.w(TAG, "Unknown message: " + message); + switch (type) { + case MCS_DATA_MESSAGE_STANZA_TAG: + handleCloudMessage((DataMessageStanza) message); + break; + case MCS_HEARTBEAT_PING_TAG: + handleHearbeatPing((HeartbeatPing) message); + break; + case MCS_HEARTBEAT_ACK_TAG: + handleHeartbeatAck((HeartbeatAck) message); + break; + case MCS_CLOSE_TAG: + handleClose((Close) message); + break; + case MCS_LOGIN_RESPONSE_TAG: + handleLoginResponse((LoginResponse) message); + break; + default: + Log.w(TAG, "Unknown message: " + message); } resetCurrentDelay(); } catch (Exception e) { @@ -399,7 +440,7 @@ public class McsService extends Service implements Handler.Callback { } private void handleTeardown(android.os.Message msg) { - sendOutputStream(MSG_TEARDOWN, msg.obj); + sendOutputStream(MSG_TEARDOWN, msg.arg1, msg.obj); if (inputStream != null) { inputStream.close(); inputStream = null; @@ -413,7 +454,10 @@ public class McsService extends Service implements Handler.Callback { alarmManager.cancel(heartbeatIntent); if (wakeLock != null) { - wakeLock.release(); + try { + wakeLock.release(); + } catch (Exception ignored) { + } } } } diff --git a/play-services-core/src/main/java/org/microg/gms/gcm/PushRegisterService.java b/play-services-core/src/main/java/org/microg/gms/gcm/PushRegisterService.java index 9c77d54b..28c1df3f 100644 --- a/play-services-core/src/main/java/org/microg/gms/gcm/PushRegisterService.java +++ b/play-services-core/src/main/java/org/microg/gms/gcm/PushRegisterService.java @@ -32,11 +32,24 @@ import org.microg.gms.common.Utils; import java.io.IOException; +import static org.microg.gms.gcm.GcmConstants.ACTION_C2DM_REGISTER; +import static org.microg.gms.gcm.GcmConstants.ACTION_C2DM_REGISTRATION; +import static org.microg.gms.gcm.GcmConstants.ACTION_C2DM_UNREGISTER; +import static org.microg.gms.gcm.GcmConstants.ERROR_SERVICE_NOT_AVAILABLE; +import static org.microg.gms.gcm.GcmConstants.EXTRA_APP; +import static org.microg.gms.gcm.GcmConstants.EXTRA_ERROR; +import static org.microg.gms.gcm.GcmConstants.EXTRA_MESSENGER; +import static org.microg.gms.gcm.GcmConstants.EXTRA_REGISTRATION_ID; +import static org.microg.gms.gcm.GcmConstants.EXTRA_RETRY_AFTER; +import static org.microg.gms.gcm.GcmConstants.EXTRA_SENDER; +import static org.microg.gms.gcm.GcmConstants.EXTRA_UNREGISTERED; + public class PushRegisterService extends IntentService { private static final String TAG = "GmsGcmRegisterSvc"; private static final String REMOVED = "%%REMOVED%%"; private static final String ERROR = "%%ERROR%%"; + private static final String GCM_REGISTRATION_PREF = "gcm_registrations"; public PushRegisterService() { super(TAG); @@ -44,19 +57,17 @@ public class PushRegisterService extends IntentService { } private SharedPreferences getSharedPreferences() { - return getSharedPreferences("gcm_registrations", MODE_PRIVATE); + return getSharedPreferences(GCM_REGISTRATION_PREF, MODE_PRIVATE); } @Override protected void onHandleIntent(Intent intent) { Log.d(TAG, "onHandleIntent: " + intent); try { - if (intent != null && intent.getAction() != null) { - if (intent.getAction().equalsIgnoreCase("com.google.android.c2dm.intent.REGISTER")) { - register(intent); - } else if (intent.getAction().equalsIgnoreCase("com.google.android.c2dm.intent.UNREGISTER")) { - unregister(intent); - } + if (ACTION_C2DM_REGISTER.equals(intent.getAction())) { + register(intent); + } else if (ACTION_C2DM_UNREGISTER.equals(intent.getAction())) { + unregister(intent); } } catch (Exception e) { Log.w(TAG, e); @@ -73,27 +84,27 @@ public class PushRegisterService extends IntentService { } private void register(Intent intent) { - PendingIntent pendingIntent = intent.getParcelableExtra("app"); - String sender = intent.getStringExtra("sender"); + PendingIntent pendingIntent = intent.getParcelableExtra(EXTRA_APP); + String sender = intent.getStringExtra(EXTRA_SENDER); String app = packageFromPendingIntent(pendingIntent); - Log.d(TAG, "register[res]: " + intent.toString() + " extras=" + intent.getExtras()); + Log.d(TAG, "register[req]: " + intent.toString() + " extras=" + intent.getExtras()); - Intent outIntent = new Intent("com.google.android.c2dm.intent.REGISTRATION"); + Intent outIntent = new Intent(ACTION_C2DM_REGISTRATION); String appSignature = PackageUtils.firstSignatureDigest(this, app); String regId = register(this, app, appSignature, sender, null, false).token; if (regId != null) { - outIntent.putExtra("registration_id", regId); + outIntent.putExtra(EXTRA_REGISTRATION_ID, regId); getSharedPreferences().edit().putString(app + ":" + appSignature, regId).apply(); } else { - outIntent.putExtra("error", "SERVICE_NOT_AVAILABLE"); + outIntent.putExtra(EXTRA_ERROR, ERROR_SERVICE_NOT_AVAILABLE); getSharedPreferences().edit().putString(app + ":" + appSignature, "-").apply(); } Log.d(TAG, "register[res]: " + outIntent + " extras=" + outIntent.getExtras()); try { - if (intent.hasExtra("google.messenger")) { - Messenger messenger = intent.getParcelableExtra("google.messenger"); + if (intent.hasExtra(EXTRA_MESSENGER)) { + Messenger messenger = intent.getParcelableExtra(EXTRA_MESSENGER); Message message = Message.obtain(); message.obj = outIntent; messenger.send(message); @@ -127,35 +138,34 @@ public class PushRegisterService extends IntentService { } private void unregister(Intent intent) { - PendingIntent pendingIntent = intent.getParcelableExtra("app"); + PendingIntent pendingIntent = intent.getParcelableExtra(EXTRA_APP); String app = packageFromPendingIntent(pendingIntent); - Log.d(TAG, "unregister[res]: " + intent.toString() + " extras=" + intent.getExtras()); + Log.d(TAG, "unregister[req]: " + intent.toString() + " extras=" + intent.getExtras()); - Intent outIntent = new Intent("com.google.android.c2dm.intent.REGISTRATION"); + Intent outIntent = new Intent(ACTION_C2DM_REGISTRATION); String appSignature = PackageUtils.firstSignatureDigest(this, app); if (REMOVED.equals(getSharedPreferences().getString(app + ":" + appSignature, null))) { - outIntent.putExtra("unregistered", app); + outIntent.putExtra(EXTRA_UNREGISTERED, app); } else { RegisterResponse response = register(this, app, appSignature, null, null, true); if (!app.equals(response.deleted)) { - outIntent.putExtra("error", "SERVICE_NOT_AVAILABLE"); + outIntent.putExtra(EXTRA_ERROR, ERROR_SERVICE_NOT_AVAILABLE); getSharedPreferences().edit().putString(app + ":" + PackageUtils.firstSignatureDigest(this, app), ERROR).apply(); - long retry = 0; if (response.retryAfter != null && !response.retryAfter.contains(":")) { - outIntent.putExtra("Retry-After", Long.parseLong(response.retryAfter)); + outIntent.putExtra(EXTRA_RETRY_AFTER, Long.parseLong(response.retryAfter)); } } else { - outIntent.putExtra("unregistered", app); + outIntent.putExtra(EXTRA_UNREGISTERED, app); getSharedPreferences().edit().putString(app + ":" + PackageUtils.firstSignatureDigest(this, app), REMOVED).apply(); } } Log.d(TAG, "unregister[res]: " + outIntent.toString() + " extras=" + outIntent.getExtras()); try { - if (intent.hasExtra("google.messenger")) { - Messenger messenger = intent.getParcelableExtra("google.messenger"); + if (intent.hasExtra(EXTRA_MESSENGER)) { + Messenger messenger = intent.getParcelableExtra(EXTRA_MESSENGER); Message message = Message.obtain(); message.obj = outIntent; messenger.send(message); diff --git a/play-services-core/src/main/java/org/microg/gms/gcm/TriggerReceiver.java b/play-services-core/src/main/java/org/microg/gms/gcm/TriggerReceiver.java index 13df88ea..96ec5b94 100644 --- a/play-services-core/src/main/java/org/microg/gms/gcm/TriggerReceiver.java +++ b/play-services-core/src/main/java/org/microg/gms/gcm/TriggerReceiver.java @@ -26,9 +26,9 @@ import android.util.Log; import org.microg.gms.checkin.LastCheckinInfo; -import static org.microg.gms.gcm.Constants.ACTION_CONNECT; -import static org.microg.gms.gcm.Constants.ACTION_HEARTBEAT; -import static org.microg.gms.gcm.Constants.EXTRA_REASON; +import static org.microg.gms.gcm.McsConstants.ACTION_CONNECT; +import static org.microg.gms.gcm.McsConstants.ACTION_HEARTBEAT; +import static org.microg.gms.gcm.McsConstants.EXTRA_REASON; public class TriggerReceiver extends WakefulBroadcastReceiver { private static final String TAG = "GmsGcmTrigger"; diff --git a/play-services-core/src/main/java/org/microg/gms/location/GoogleLocationManager.java b/play-services-core/src/main/java/org/microg/gms/location/GoogleLocationManager.java index 5c6070ca..e7a4fe73 100644 --- a/play-services-core/src/main/java/org/microg/gms/location/GoogleLocationManager.java +++ b/play-services-core/src/main/java/org/microg/gms/location/GoogleLocationManager.java @@ -16,15 +16,21 @@ package org.microg.gms.location; +import android.Manifest; import android.app.PendingIntent; import android.content.Context; import android.location.Location; import android.location.LocationManager; +import android.support.v4.content.ContextCompat; +import android.widget.Toast; +import com.google.android.gms.R; import com.google.android.gms.location.ILocationListener; import com.google.android.gms.location.LocationRequest; import com.google.android.gms.location.internal.LocationRequestUpdateData; +import org.microg.gms.common.Utils; + import java.util.ArrayList; import java.util.List; @@ -41,18 +47,25 @@ public class GoogleLocationManager implements LocationChangeListener { private static final long SWITCH_ON_FRESHNESS_CLIFF_MS = 30000; // 30 seconds private static final String ACCESS_MOCK_LOCATION = "android.permission.ACCESS_MOCK_LOCATION"; - private Context context; - private LocationManager locationManager; - private RealLocationProvider gpsProvider; - private RealLocationProvider networkProvider; - private MockLocationProvider mockProvider; - private List currentRequests = new ArrayList(); + private final Context context; + private final RealLocationProvider gpsProvider; + private final RealLocationProvider networkProvider; + private final MockLocationProvider mockProvider; + private final List currentRequests = new ArrayList(); public GoogleLocationManager(Context context) { this.context = context; - locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); - gpsProvider = new RealLocationProvider(locationManager, GPS_PROVIDER, this); - networkProvider = new RealLocationProvider(locationManager, NETWORK_PROVIDER, this); + LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + if (Utils.hasSelfPermissionOrNotify(context, Manifest.permission.ACCESS_FINE_LOCATION)) { + this.gpsProvider = new RealLocationProvider(locationManager, GPS_PROVIDER, this); + } else { + this.gpsProvider = null; + } + if (Utils.hasSelfPermissionOrNotify(context, Manifest.permission.ACCESS_COARSE_LOCATION)) { + this.networkProvider = new RealLocationProvider(locationManager, NETWORK_PROVIDER, this); + } else { + this.networkProvider = null; + } mockProvider = new MockLocationProvider(this); } @@ -64,8 +77,8 @@ public class GoogleLocationManager implements LocationChangeListener { if (mockProvider.getLocation() != null) return mockProvider.getLocation(); if (gpsPermission) { - Location network = networkProvider.getLastLocation(); - Location gps = gpsProvider.getLastLocation(); + Location network = networkProvider == null ? null : networkProvider.getLastLocation(); + Location gps = gpsProvider == null ? null : gpsProvider.getLastLocation(); if (network == null) return gps; if (gps == null) @@ -74,7 +87,7 @@ public class GoogleLocationManager implements LocationChangeListener { return gps; return network; } else if (networkPermission) { - Location network = networkProvider.getLastLocation(); + Location network = networkProvider == null ? null : networkProvider.getLastLocation(); if (network != null && network.getExtras() != null && network.getExtras().getParcelable("no_gps_location") instanceof Location) { network = network.getExtras().getParcelable("no_gps_location"); } @@ -97,9 +110,9 @@ public class GoogleLocationManager implements LocationChangeListener { private void requestLocationUpdates(LocationRequestHelper request) { currentRequests.add(request); - if (request.hasFinePermission && request.locationRequest.getPriority() == PRIORITY_HIGH_ACCURACY) + if (gpsProvider != null && request.hasFinePermission && request.locationRequest.getPriority() == PRIORITY_HIGH_ACCURACY) gpsProvider.addRequest(request); - if (request.hasCoarsePermission && request.locationRequest.getPriority() != PRIORITY_NO_POWER) + if (networkProvider != null && request.hasCoarsePermission && request.locationRequest.getPriority() != PRIORITY_NO_POWER) networkProvider.addRequest(request); } @@ -117,8 +130,8 @@ public class GoogleLocationManager implements LocationChangeListener { private void removeLocationUpdates(LocationRequestHelper request) { currentRequests.remove(request); - gpsProvider.removeRequest(request); - networkProvider.removeRequest(request); + if (gpsProvider != null) gpsProvider.removeRequest(request); + if (networkProvider != null) networkProvider.removeRequest(request); } public void removeLocationUpdates(ILocationListener listener, String packageName) { diff --git a/play-services-core/src/main/java/org/microg/gms/location/MockLocationProvider.java b/play-services-core/src/main/java/org/microg/gms/location/MockLocationProvider.java index 31a42d60..fe3ce0a8 100644 --- a/play-services-core/src/main/java/org/microg/gms/location/MockLocationProvider.java +++ b/play-services-core/src/main/java/org/microg/gms/location/MockLocationProvider.java @@ -19,7 +19,7 @@ package org.microg.gms.location; import android.location.Location; import android.os.Bundle; -import static org.microg.gms.common.Constants.KEY_MOCK_LOCATION; +import static org.microg.gms.location.LocationConstants.KEY_MOCK_LOCATION; public class MockLocationProvider { private boolean mockEnabled = false; @@ -44,5 +44,6 @@ public class MockLocationProvider { } mockLocation.getExtras().putBoolean(KEY_MOCK_LOCATION, false); this.mockLocation = mockLocation; + this.changeListener.onLocationChanged(); } } diff --git a/play-services-core/src/main/java/org/microg/gms/location/RealLocationProvider.java b/play-services-core/src/main/java/org/microg/gms/location/RealLocationProvider.java index 13486656..9be355b6 100644 --- a/play-services-core/src/main/java/org/microg/gms/location/RealLocationProvider.java +++ b/play-services-core/src/main/java/org/microg/gms/location/RealLocationProvider.java @@ -27,17 +27,19 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +@SuppressWarnings("ResourceType") public class RealLocationProvider { - public static final String TAG = "GmsLocProviderReal"; - private Location lastLocation; - private LocationManager locationManager; - private String name; + + private final LocationManager locationManager; + private final String name; private final AtomicBoolean connected = new AtomicBoolean(false); + private final LocationChangeListener changeListener; + private long connectedMinTime; private float connectedMinDistance; + private Location lastLocation; private List requests = new ArrayList(); - private final LocationChangeListener changeListener; private LocationListener listener = new LocationListener() { @Override public void onLocationChanged(Location location) { @@ -62,7 +64,7 @@ public class RealLocationProvider { }; public RealLocationProvider(LocationManager locationManager, String name, - LocationChangeListener changeListener) { + LocationChangeListener changeListener) { this.locationManager = locationManager; this.name = name; this.changeListener = changeListener; @@ -70,13 +72,17 @@ public class RealLocationProvider { } private void updateLastLocation() { - lastLocation = locationManager.getLastKnownLocation(name); + Location newLocation = locationManager.getLastKnownLocation(name); + if (newLocation != null) lastLocation = newLocation; } public Location getLastLocation() { if (!connected.get()) { updateLastLocation(); } + if (lastLocation == null) { + Log.d(TAG, "uh-ok: last location for " + name + " is null!"); + } return lastLocation; } @@ -102,8 +108,7 @@ public class RealLocationProvider { float minDistance = Float.MAX_VALUE; for (LocationRequestHelper request : requests) { minTime = Math.min(request.locationRequest.getInterval(), minTime); - minDistance = Math - .min(request.locationRequest.getSmallestDesplacement(), minDistance); + minDistance = Math.min(request.locationRequest.getSmallestDesplacement(), minDistance); } if (connected.get()) { if (connectedMinTime != minTime || connectedMinDistance != minDistance) { @@ -112,12 +117,9 @@ public class RealLocationProvider { Looper.getMainLooper()); } } else { - locationManager.requestLocationUpdates(name, minTime, minDistance, listener, - Looper.getMainLooper()); + locationManager.requestLocationUpdates(name, minTime, minDistance, listener, Looper.getMainLooper()); } - Log.d(TAG, - name + ": requesting location updates. minTime=" + minTime + " minDistance=" + - minDistance); + Log.d(TAG, name + ": requesting location updates. minTime=" + minTime + " minDistance=" + minDistance); connected.set(true); connectedMinTime = minTime; connectedMinDistance = minDistance; diff --git a/play-services-core/src/main/java/org/microg/gms/maps/BackendMap.java b/play-services-core/src/main/java/org/microg/gms/maps/BackendMap.java index 72656c6b..cd9c555a 100644 --- a/play-services-core/src/main/java/org/microg/gms/maps/BackendMap.java +++ b/play-services-core/src/main/java/org/microg/gms/maps/BackendMap.java @@ -17,88 +17,50 @@ package org.microg.gms.maps; import android.content.Context; -import android.graphics.BitmapFactory; import android.util.Log; import android.view.View; -import com.google.android.gms.R; import com.google.android.gms.maps.model.CameraPosition; import org.microg.gms.maps.camera.CameraUpdate; -import org.microg.gms.maps.data.SharedTileCache; -import org.microg.gms.maps.markup.ClearableVectorLayer; import org.microg.gms.maps.markup.DrawableMarkup; import org.microg.gms.maps.markup.MarkerItemMarkup; import org.microg.gms.maps.markup.Markup; -import org.oscim.android.MapView; -import org.oscim.android.canvas.AndroidBitmap; import org.oscim.core.MapPosition; import org.oscim.core.Point; import org.oscim.event.Event; import org.oscim.event.MotionEvent; import org.oscim.layers.marker.ItemizedLayer; import org.oscim.layers.marker.MarkerItem; -import org.oscim.layers.marker.MarkerSymbol; -import org.oscim.layers.tile.buildings.BuildingLayer; -import org.oscim.layers.tile.vector.VectorTileLayer; -import org.oscim.layers.tile.vector.labeling.LabelLayer; import org.oscim.layers.vector.geometries.Drawable; -import org.oscim.map.Layers; -import org.oscim.map.Map; import org.oscim.map.Viewport; -import org.oscim.theme.VtmThemes; -import org.oscim.tiling.ITileCache; -import org.oscim.tiling.source.oscimap4.OSciMap4TileSource; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; +import java.util.Map; -public class BackendMap implements ItemizedLayer.OnItemGestureListener, Map.InputListener { +public class BackendMap implements ItemizedLayer.OnItemGestureListener, org.oscim.map.Map.InputListener, org.oscim.map.Map.UpdateListener { private final static String TAG = "GmsMapBackend"; private final Context context; - private final MapView mapView; - private final LabelLayer labels; - private final BuildingLayer buildings; - private final VectorTileLayer baseLayer; - private final OSciMap4TileSource tileSource; - private final ITileCache cache; - private final ItemizedLayer items; - private java.util.Map markupMap = new HashMap(); - private List drawableMarkups = new ArrayList(); - private ClearableVectorLayer drawables; + private final BackendMapView mapView; + private final CameraUpdateListener cameraUpdateListener; + private final Map markupMap = new HashMap(); + private final List drawableMarkups = new ArrayList(); private MarkerItemMarkup currentlyDraggedItem; private float dragLastX = -1; private float dragLastY = -1; public BackendMap(Context context, final CameraUpdateListener cameraUpdateListener) { this.context = context; - mapView = new MapView(new ContextContainer(context)); - cache = new SharedTileCache(context); - cache.setCacheSize(512 * (1 << 10)); - tileSource = new OSciMap4TileSource(); - tileSource.setCache(cache); - baseLayer = mapView.map().setBaseMap(tileSource); - Layers layers = mapView.map().layers(); - layers.add(labels = new LabelLayer(mapView.map(), baseLayer)); - layers.add(drawables = new ClearableVectorLayer(mapView.map())); - layers.add(buildings = new BuildingLayer(mapView.map(), baseLayer)); - layers.add(items = new ItemizedLayer(mapView.map(), new MarkerSymbol(new AndroidBitmap(BitmapFactory - .decodeResource(ResourcesContainer.get(), R.drawable.nop)), 0.5F, 1))); - items.setOnItemGestureListener(this); - mapView.map().setTheme(VtmThemes.DEFAULT); + this.cameraUpdateListener = cameraUpdateListener; + mapView = new BackendMapView(new ContextContainer(context)); + mapView.items().setOnItemGestureListener(this); mapView.map().input.bind(this); - mapView.map().events.bind(new Map.UpdateListener() { - - @Override - public void onMapEvent(Event event, MapPosition mapPosition) { - cameraUpdateListener.onCameraUpdate(GmsMapsTypeHelper.toCameraPosition(mapPosition)); - } - }); + mapView.map().events.bind(this); } public Viewport getViewport() { @@ -110,23 +72,11 @@ public class BackendMap implements ItemizedLayer.OnItemGestureListener T add(T markup) { if (markup == null) return null; markupMap.put(markup.getId(), markup); - items.addItem(markup.getMarkerItem(context)); + mapView.items().addItem(markup.getMarkerItem(context)); redraw(); return markup; } public synchronized void clear() { markupMap.clear(); - items.removeAllItems(); + mapView.items().removeAllItems(); drawableMarkups.clear(); - drawables.clear(); + mapView.drawables().clear(); redraw(); } public synchronized void remove(Markup markup) { if (markup instanceof MarkerItemMarkup) { markupMap.remove(markup.getId()); - items.removeItem(items.getByUid(markup.getId())); + mapView.items().removeItem(mapView.items().getByUid(markup.getId())); } else if (markup instanceof DrawableMarkup) { drawableMarkups.remove(markup); updateDrawableLayer(); - drawables.update(); + mapView.drawables().update(); } redraw(); } @@ -221,11 +171,11 @@ public class BackendMap implements ItemizedLayer.OnItemGestureListener items; + private ClearableVectorLayer drawables; + + @Override + public void onResume() { + super.onResume(); + } + + @Override + public void onPause() { + super.onPause(); + } + + public BackendMapView(Context context) { + super(context); + initialize(); + } + + public BackendMapView(Context context, AttributeSet attributeSet) { + super(context, attributeSet); + initialize(); + } + + ItemizedLayer items() { + return items; + } + + BuildingLayer buildings() { + return buildings; + } + + ClearableVectorLayer drawables() { + return drawables; + } + + private void initialize() { + ITileCache cache = new SharedTileCache(getContext()); + cache.setCacheSize(512 * (1 << 10)); + OSciMap4TileSource tileSource = new OSciMap4TileSource(); + tileSource.setCache(cache); + VectorTileLayer baseLayer = map().setBaseMap(tileSource); + Layers layers = map().layers(); + layers.add(labels = new LabelLayer(map(), baseLayer)); + layers.add(drawables = new ClearableVectorLayer(map())); + layers.add(buildings = new BuildingLayer(map(), baseLayer)); + layers.add(items = new ItemizedLayer(map(), new MarkerSymbol( + new AndroidBitmap(BitmapFactory.decodeResource(getContext().getResources(), R.drawable.nop)), 0.5F, 1))); + map().setTheme(VtmThemes.DEFAULT); + } +} diff --git a/play-services-core/src/main/java/org/microg/gms/maps/markup/PolylineImpl.java b/play-services-core/src/main/java/org/microg/gms/maps/markup/PolylineImpl.java index bd52bbef..1ffeb4fe 100644 --- a/play-services-core/src/main/java/org/microg/gms/maps/markup/PolylineImpl.java +++ b/play-services-core/src/main/java/org/microg/gms/maps/markup/PolylineImpl.java @@ -33,9 +33,6 @@ import org.oscim.map.Map; import java.util.ArrayList; import java.util.List; -/** - * TODO - */ public class PolylineImpl extends IPolylineDelegate.Stub implements DrawableMarkup { private static final String TAG = "GmsMapsPolylineImpl"; diff --git a/play-services-core/src/main/java/org/microg/gms/people/PeopleServiceImpl.java b/play-services-core/src/main/java/org/microg/gms/people/PeopleServiceImpl.java index 7923affd..99157257 100644 --- a/play-services-core/src/main/java/org/microg/gms/people/PeopleServiceImpl.java +++ b/play-services-core/src/main/java/org/microg/gms/people/PeopleServiceImpl.java @@ -34,6 +34,7 @@ import com.google.android.gms.people.internal.IPeopleService; import com.google.android.gms.people.model.AccountMetadata; import org.microg.gms.common.NonCancelToken; +import org.microg.gms.common.PackageUtils; import java.io.File; @@ -48,6 +49,7 @@ public class PeopleServiceImpl extends IPeopleService.Stub { @Override public void loadOwners(final IPeopleCallbacks callbacks, boolean var2, boolean var3, final String accountName, String var5, int sortOrder) { Log.d(TAG, "loadOwners: " + var2 + ", " + var3 + ", " + accountName + ", " + var5 + ", " + sortOrder); + PackageUtils.assertExtendedAccess(context); AccountManager accountManager = AccountManager.get(context); Bundle accountMetadata = new Bundle(); String accountType = context.getString(R.string.google_account_type); @@ -85,6 +87,7 @@ public class PeopleServiceImpl extends IPeopleService.Stub { @Override public void loadCircles(IPeopleCallbacks callbacks, String account, String pageGaiaId, String circleId, int type, String var6, boolean var7) throws RemoteException { Log.d(TAG, "loadCircles: " + account + ", " + pageGaiaId + ", " + circleId + ", " + type + ", " + var6 + ", " + var7); + PackageUtils.assertExtendedAccess(context); try { DatabaseHelper databaseHelper = new DatabaseHelper(context); Cursor owner = databaseHelper.getOwner(account); @@ -111,6 +114,7 @@ public class PeopleServiceImpl extends IPeopleService.Stub { @Override public ICancelToken loadOwnerAvatar(final IPeopleCallbacks callbacks, final String account, String pageId, int size, int flags) { Log.d(TAG, "loadOwnerAvatar: " + account + ", " + pageId + ", " + size + ", " + flags); + PackageUtils.assertExtendedAccess(context); final Thread thread = new Thread(new Runnable() { @Override public void run() { diff --git a/play-services-core/src/main/java/org/microg/gms/ui/PlacePickerActivity.java b/play-services-core/src/main/java/org/microg/gms/ui/PlacePickerActivity.java index 3aa2a15d..756e0417 100644 --- a/play-services-core/src/main/java/org/microg/gms/ui/PlacePickerActivity.java +++ b/play-services-core/src/main/java/org/microg/gms/ui/PlacePickerActivity.java @@ -17,37 +17,52 @@ package org.microg.gms.ui; import android.content.Intent; +import android.location.Address; +import android.location.Geocoder; import android.os.Build; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.SearchView; import android.support.v7.widget.Toolbar; +import android.text.TextUtils; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; import android.view.MenuItem; +import android.view.View; +import android.widget.TextView; import com.google.android.gms.R; +import com.google.android.gms.common.api.CommonStatusCodes; +import com.google.android.gms.common.api.Status; +import com.google.android.gms.location.places.internal.PlaceImpl; +import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.LatLngBounds; -public class PlacePickerActivity extends AppCompatActivity { +import org.microg.gms.location.LocationConstants; +import org.microg.gms.maps.BackendMapView; +import org.microg.gms.maps.GmsMapsTypeHelper; +import org.microg.safeparcel.SafeParcelUtil; +import org.oscim.core.MapPosition; +import org.oscim.event.Event; +import org.oscim.map.Map; + +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +public class PlacePickerActivity extends AppCompatActivity implements Map.UpdateListener { private static final String TAG = "GmsPlacePicker"; - private static final String EXTRA_PRIMARY_COLOR = "primary_color"; - private static final String EXTRA_PRIMARY_COLOR_DARK = "primary_color_dark"; - private static final String EXTRA_CLIENT_VERSION = "gmscore_client_jar_version"; - private static final String EXTRA_BOUNDS = "latlng_bounds"; - - private static final String EXTRA_ATTRIBUTION = "third_party_attributions"; - private static final String EXTRA_FINAL_BOUNDS = "final_latlng_bounds"; - private static final String EXTRA_PLACE = "selected_place"; - private static final String EXTRA_STATUS = "status"; - - private int resultCode; + private PlaceImpl place; + private BackendMapView mapView; private Intent resultIntent; + private AtomicBoolean geocoderInProgress = new AtomicBoolean(false); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - resultCode = RESULT_CANCELED; resultIntent = new Intent(); - if (getIntent().hasExtra(EXTRA_BOUNDS)) - resultIntent.putExtra(EXTRA_FINAL_BOUNDS, getIntent().getParcelableExtra(EXTRA_BOUNDS)); + place = new PlaceImpl(); setContentView(R.layout.pick_place); @@ -55,9 +70,58 @@ public class PlacePickerActivity extends AppCompatActivity { setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayShowHomeEnabled(true); - toolbar.setBackgroundColor(getIntent().getIntExtra(EXTRA_PRIMARY_COLOR, 0)); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) - getWindow().setStatusBarColor(getIntent().getIntExtra(EXTRA_PRIMARY_COLOR_DARK, 0)); + + if (getIntent().hasExtra(LocationConstants.EXTRA_PRIMARY_COLOR)) { + toolbar.setBackgroundColor(getIntent().getIntExtra(LocationConstants.EXTRA_PRIMARY_COLOR, 0)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) + getWindow().setStatusBarColor(getIntent().getIntExtra(LocationConstants.EXTRA_PRIMARY_COLOR_DARK, 0)); + ((TextView) findViewById(R.id.place_picker_title)).setTextColor(getIntent().getIntExtra(LocationConstants.EXTRA_PRIMARY_COLOR_DARK, 0)); + } + + mapView = (BackendMapView) findViewById(R.id.map); + mapView.map().getEventLayer().enableRotation(false); + mapView.map().getEventLayer().enableTilt(false); + mapView.map().events.bind(this); + + LatLngBounds latLngBounds = getIntent().getParcelableExtra(LocationConstants.EXTRA_BOUNDS); + if (latLngBounds != null) { + place.viewport = latLngBounds; + mapView.map().getMapPosition().setByBoundingBox(GmsMapsTypeHelper.fromLatLngBounds(latLngBounds), + mapView.map().getWidth(), mapView.map().getHeight()); + } + + findViewById(R.id.place_picker_select).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + resultIntent.putExtra(LocationConstants.EXTRA_STATUS, SafeParcelUtil.asByteArray(new Status(CommonStatusCodes.SUCCESS))); + resultIntent.putExtra(LocationConstants.EXTRA_PLACE, SafeParcelUtil.asByteArray(place)); + resultIntent.putExtra(LocationConstants.EXTRA_FINAL_BOUNDS, SafeParcelUtil.asByteArray(place.viewport)); + setResult(RESULT_OK, resultIntent); + finish(); + } + }); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.pick_place, menu); + SearchView searchView = (SearchView) menu.findItem(R.id.menu_action_search).getActionView(); + // TODO: search + return true; + } + + @Override + protected void onResume() { + super.onResume(); + mapView.onResume(); + } + + @Override + protected void onPause() { + mapView.onPause(); + super.onPause(); } @Override @@ -72,6 +136,57 @@ public class PlacePickerActivity extends AppCompatActivity { @Override protected void onDestroy() { super.onDestroy(); - setResult(resultCode, resultIntent); + } + + @Override + public void onMapEvent(Event event, MapPosition position) { + place.viewport = GmsMapsTypeHelper.toLatLngBounds(mapView.map().viewport().getBBox(null, 0)); + resultIntent.putExtra(LocationConstants.EXTRA_FINAL_BOUNDS, place.viewport); + place.latLng = GmsMapsTypeHelper.toLatLng(position.getGeoPoint()); + place.name = getString(R.string.place_picker_location_lat_lng, place.latLng.latitude, place.latLng.longitude); + place.address = null; + updateInfoText(); + if (geocoderInProgress.compareAndSet(false, true)) { + new Thread(new Runnable() { + @Override + public void run() { + try { + LatLng ll = null; + while (ll != place.latLng) { + ll = place.latLng; + Thread.sleep(1000); + } + Geocoder geocoder = new Geocoder(PlacePickerActivity.this); + List
addresses = geocoder.getFromLocation(place.latLng.latitude, place.latLng.longitude, 1); + if (addresses != null && !addresses.isEmpty() && addresses.get(0).getMaxAddressLineIndex() > 0) { + Address address = addresses.get(0); + StringBuilder sb = new StringBuilder(address.getAddressLine(0)); + for (int i = 1; i < address.getMaxAddressLineIndex(); ++i) { + sb.append(", ").append(address.getAddressLine(i)); + } + if (place.latLng == ll) { + place.address = sb.toString(); + place.name = address.getFeatureName(); + if (TextUtils.isEmpty(place.name)) place.name = place.address; + runOnUiThread(new Runnable() { + @Override + public void run() { + updateInfoText(); + } + }); + } + } + } catch (Exception ignored) { + Log.w(TAG, ignored); + } finally { + geocoderInProgress.lazySet(false); + } + } + }).start(); + } + } + + private void updateInfoText() { + ((TextView) findViewById(R.id.place_picker_info)).setText(place.name); } } diff --git a/play-services-core/src/main/java/org/microg/gms/ui/SelfCheckActivity.java b/play-services-core/src/main/java/org/microg/gms/ui/SelfCheckActivity.java deleted file mode 100644 index 31d8e569..00000000 --- a/play-services-core/src/main/java/org/microg/gms/ui/SelfCheckActivity.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2013-2015 microG Project Team - * - * 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 org.microg.gms.ui; - -import org.microg.tools.selfcheck.AbstractSelfCheckActivity; -import org.microg.tools.selfcheck.InstalledPackagesChecks; -import org.microg.tools.selfcheck.RomSpoofSignatureChecks; -import org.microg.tools.selfcheck.SelfCheckGroup; - -import java.util.List; - -public class SelfCheckActivity extends AbstractSelfCheckActivity implements SelfCheckGroup.ResultCollector { - - protected void prepareSelfCheckList(List checks) { - checks.add(new RomSpoofSignatureChecks()); - checks.add(new InstalledPackagesChecks()); - } -} diff --git a/play-services-core/src/main/java/org/microg/gms/ui/SettingsActivity.java b/play-services-core/src/main/java/org/microg/gms/ui/SettingsActivity.java index 56051448..7b66383a 100644 --- a/play-services-core/src/main/java/org/microg/gms/ui/SettingsActivity.java +++ b/play-services-core/src/main/java/org/microg/gms/ui/SettingsActivity.java @@ -17,13 +17,30 @@ package org.microg.gms.ui; import android.os.Bundle; -import android.support.v4.app.FragmentActivity; +import android.preference.Preference; +import android.support.annotation.NonNull; +import android.support.v4.app.FragmentTransaction; import android.support.v4.preference.PreferenceFragment; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; +import android.view.LayoutInflater; import com.google.android.gms.R; +import org.microg.tools.selfcheck.InstalledPackagesChecks; +import org.microg.tools.selfcheck.NlpOsCompatChecks; +import org.microg.tools.selfcheck.NlpStatusChecks; +import org.microg.tools.selfcheck.PermissionChecks; +import org.microg.tools.selfcheck.RomSpoofSignatureChecks; +import org.microg.tools.selfcheck.SelfCheckGroup; +import org.microg.tools.ui.AbstractAboutFragment; +import org.microg.tools.ui.AbstractSelfCheckFragment; + +import java.util.List; + +import static android.os.Build.VERSION.SDK_INT; +import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1; + public class SettingsActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { @@ -31,7 +48,8 @@ public class SettingsActivity extends AppCompatActivity { setContentView(R.layout.settings_activity); setSupportActionBar((Toolbar) findViewById(R.id.toolbar)); getSupportFragmentManager().beginTransaction() - .replace(R.id.content_wrapper, new MyPreferenceFragment()).commit(); + .replace(R.id.content_wrapper, new MyPreferenceFragment()) + .commit(); } public static class MyPreferenceFragment extends PreferenceFragment { @@ -40,6 +58,64 @@ public class SettingsActivity extends AppCompatActivity { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.gms_preferences); + + findPreference(getString(R.string.self_check_title)) + .setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + getFragmentManager().beginTransaction() + .addToBackStack("root") + .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) + .replace(R.id.content_wrapper, new MySelfCheckFragment()) + .commit(); + return true; + } + }); + findPreference(getString(R.string.pref_about_title)) + .setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + getFragmentManager().beginTransaction() + .addToBackStack("root") + .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) + .replace(R.id.content_wrapper, new MyAboutFragment()) + .commit(); + return true; + } + }); + } + } + + public static class MySelfCheckFragment extends AbstractSelfCheckFragment { + + @Override + protected void prepareSelfCheckList(List checks) { + checks.add(new RomSpoofSignatureChecks()); + checks.add(new InstalledPackagesChecks()); + if (SDK_INT > LOLLIPOP_MR1) { + checks.add(new PermissionChecks()); + } + checks.add(new NlpOsCompatChecks()); + checks.add(new NlpStatusChecks()); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + reset(LayoutInflater.from(getContext())); + } + } + + public static class MyAboutFragment extends AbstractAboutFragment { + + @Override + protected void collectLibraries(List libraries) { + libraries.add(new Library("org.microg.gms.api", "microG GmsApi", "Apache License 2.0, Copyright © microG Team")); + libraries.add(new Library("org.microg.safeparcel", "microG SafeParcel", "Apache License 2.0, Copyright © microG Team")); + libraries.add(new Library("org.microg.nlp", "microG UnifiedNlp", "Apache License 2.0, Copyright © microG Team")); + libraries.add(new Library("org.microg.nlp.api", "microG UnifiedNlp Api", "Apache License 2.0, Copyright © microG Team")); + libraries.add(new Library("de.hdodenhof.circleimageview", "CircleImageView", "Apache License 2.0, Copyright © Henning Dodenhof")); + libraries.add(new Library("org.oscim.android", ">map", "GNU LGPLv3, Copyright © Hannes Janetzek")); + libraries.add(new Library("com.squareup.wire", "Wire Protocol Buffers", "Apache License 2.0, Copyright © Square Inc.")); } } } diff --git a/play-services-core/src/main/java/org/microg/tools/selfcheck/InstalledPackagesChecks.java b/play-services-core/src/main/java/org/microg/tools/selfcheck/InstalledPackagesChecks.java index ecb61fc7..339719de 100644 --- a/play-services-core/src/main/java/org/microg/tools/selfcheck/InstalledPackagesChecks.java +++ b/play-services-core/src/main/java/org/microg/tools/selfcheck/InstalledPackagesChecks.java @@ -23,20 +23,22 @@ import com.google.android.gms.R; import org.microg.gms.common.Constants; import org.microg.gms.common.PackageUtils; -import org.microg.tools.selfcheck.SelfCheckGroup; + +import static org.microg.tools.selfcheck.SelfCheckGroup.Result.Negative; +import static org.microg.tools.selfcheck.SelfCheckGroup.Result.Positive; public class InstalledPackagesChecks implements SelfCheckGroup { @Override public String getGroupName(Context context) { - return "Installed packages"; + return context.getString(R.string.self_check_cat_gms_packages); } @Override public void doChecks(Context context, ResultCollector collector) { - addPackageInstalledAndSignedResult(context, collector, "Play Services (GmsCore)", Constants.GMS_PACKAGE_NAME, Constants.GMS_PACKAGE_SIGNATURE_SHA1); - addPackageInstalledAndSignedResult(context, collector, "Play Store (Phonesky)", "com.android.vending", Constants.GMS_PACKAGE_SIGNATURE_SHA1); - addPackageInstalledResult(context, collector, "Services Framework (GSF)", "com.google.android.gsf"); + addPackageInstalledAndSignedResult(context, collector, context.getString(R.string.self_check_pkg_gms), Constants.GMS_PACKAGE_NAME, Constants.GMS_PACKAGE_SIGNATURE_SHA1); + addPackageInstalledAndSignedResult(context, collector, context.getString(R.string.self_check_pkg_vending), "com.android.vending", Constants.GMS_PACKAGE_SIGNATURE_SHA1); + addPackageInstalledResult(context, collector, context.getString(R.string.self_check_pkg_gsf), Constants.GSF_PACKAGE_NAME); } private void addPackageInstalledAndSignedResult(Context context, ResultCollector collector, String nicePackageName, String androidPackageName, String signatureHash) { @@ -47,7 +49,7 @@ public class InstalledPackagesChecks implements SelfCheckGroup { private boolean addPackageSignedResult(Context context, ResultCollector collector, String nicePackageName, String androidPackageName, String signatureHash) { boolean hashMatches = signatureHash.equals(PackageUtils.firstSignatureDigest(context, androidPackageName)); - collector.addResult(context.getString(R.string.self_check_name_correct_sig, nicePackageName), hashMatches, + collector.addResult(context.getString(R.string.self_check_name_correct_sig, nicePackageName), hashMatches ? Positive : Negative, context.getString(R.string.self_check_resolution_correct_sig, nicePackageName)); return hashMatches; } @@ -59,7 +61,7 @@ public class InstalledPackagesChecks implements SelfCheckGroup { } catch (PackageManager.NameNotFoundException e) { packageExists = false; } - collector.addResult(context.getString(R.string.self_check_name_app_installed, nicePackageName), packageExists, + collector.addResult(context.getString(R.string.self_check_name_app_installed, nicePackageName), packageExists ? Positive : Negative, context.getString(R.string.self_check_resolution_app_installed, nicePackageName)); return packageExists; } diff --git a/play-services-core/src/main/java/org/microg/tools/selfcheck/PermissionChecks.java b/play-services-core/src/main/java/org/microg/tools/selfcheck/PermissionChecks.java new file mode 100644 index 00000000..ab08b227 --- /dev/null +++ b/play-services-core/src/main/java/org/microg/tools/selfcheck/PermissionChecks.java @@ -0,0 +1,74 @@ +/* + * Copyright 2013-2016 microG Project Team + * + * 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 org.microg.tools.selfcheck; + +import android.Manifest; +import android.annotation.TargetApi; +import android.content.Context; +import android.content.pm.PackageManager; +import android.content.pm.PermissionGroupInfo; +import android.content.pm.PermissionInfo; +import android.os.Build; +import android.support.v4.app.Fragment; +import android.util.Log; + +import com.google.android.gms.R; + +import static org.microg.tools.selfcheck.SelfCheckGroup.Result.Negative; +import static org.microg.tools.selfcheck.SelfCheckGroup.Result.Positive; + +@TargetApi(Build.VERSION_CODES.M) +public class PermissionChecks implements SelfCheckGroup { + private static final String TAG = "SelfCheckPerms"; + + @Override + public String getGroupName(Context context) { + return context.getString(R.string.self_check_cat_permissions); + } + + @Override + public void doChecks(Context context, ResultCollector collector) { + doPermissionCheck(context, collector, Manifest.permission.ACCESS_COARSE_LOCATION); + doPermissionCheck(context, collector, Manifest.permission.ACCESS_FINE_LOCATION); + doPermissionCheck(context, collector, Manifest.permission.WRITE_EXTERNAL_STORAGE); + doPermissionCheck(context, collector, Manifest.permission.GET_ACCOUNTS); + doPermissionCheck(context, collector, Manifest.permission.READ_PHONE_STATE); + doPermissionCheck(context, collector, com.google.android.gms.Manifest.permission.SEND); + } + + private void doPermissionCheck(Context context, ResultCollector collector, final String permission) { + PackageManager pm = context.getPackageManager(); + try { + PermissionInfo info = pm.getPermissionInfo(permission, 0); + PermissionGroupInfo groupInfo = info.group != null ? pm.getPermissionGroupInfo(info.group, 0) : null; + CharSequence permLabel = info.loadLabel(pm); + CharSequence groupLabel = groupInfo != null ? groupInfo.loadLabel(pm) : permLabel; + collector.addResult(context.getString(R.string.self_check_name_permission, permLabel), + context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED ? Positive : Negative, + context.getString(R.string.self_check_resolution_permission, groupLabel), + new SelfCheckGroup.CheckResolver() { + + @Override + public void tryResolve(Fragment fragment) { + fragment.requestPermissions(new String[]{permission}, 0); + } + }); + } catch (PackageManager.NameNotFoundException e) { + Log.w(TAG, e); + } + } +} diff --git a/play-services-core/src/main/java/org/microg/tools/selfcheck/RomSpoofSignatureChecks.java b/play-services-core/src/main/java/org/microg/tools/selfcheck/RomSpoofSignatureChecks.java index b8925d27..13d783f8 100644 --- a/play-services-core/src/main/java/org/microg/tools/selfcheck/RomSpoofSignatureChecks.java +++ b/play-services-core/src/main/java/org/microg/tools/selfcheck/RomSpoofSignatureChecks.java @@ -18,12 +18,19 @@ package org.microg.tools.selfcheck; import android.content.Context; import android.content.pm.PackageManager; +import android.support.v4.app.Fragment; +import android.support.v4.content.ContextCompat; import com.google.android.gms.R; import org.microg.gms.common.Constants; import org.microg.gms.common.PackageUtils; -import org.microg.tools.selfcheck.SelfCheckGroup; + +import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static org.microg.gms.common.Constants.GMS_PACKAGE_SIGNATURE_SHA1; +import static org.microg.tools.selfcheck.SelfCheckGroup.Result.Negative; +import static org.microg.tools.selfcheck.SelfCheckGroup.Result.Positive; +import static org.microg.tools.selfcheck.SelfCheckGroup.Result.Unknown; public class RomSpoofSignatureChecks implements SelfCheckGroup { @@ -31,16 +38,16 @@ public class RomSpoofSignatureChecks implements SelfCheckGroup { @Override public String getGroupName(Context context) { - return "ROM spoof signature support"; + return context.getString(R.string.self_check_cat_fake_sig); } @Override public void doChecks(Context context, ResultCollector collector) { - if (addRomKnowsFakeSignaturePermission(context, collector)) { - if (addSystemGrantsFakeSignaturePermission(context, collector)) { - addSystemSpoofsSignature(context, collector); - } + boolean hasPermission = addRomKnowsFakeSignaturePermission(context, collector); + if (hasPermission) { + addSystemGrantsFakeSignaturePermission(context, collector); } + addSystemSpoofsSignature(context, collector); } private boolean addRomKnowsFakeSignaturePermission(Context context, ResultCollector collector) { @@ -50,21 +57,26 @@ public class RomSpoofSignatureChecks implements SelfCheckGroup { } catch (PackageManager.NameNotFoundException e) { knowsPermission = false; } - collector.addResult(context.getString(R.string.self_check_name_fake_sig_perm), knowsPermission, + collector.addResult(context.getString(R.string.self_check_name_fake_sig_perm), knowsPermission ? Positive : Unknown, context.getString(R.string.self_check_resolution_fake_sig_perm)); return knowsPermission; } private boolean addSystemGrantsFakeSignaturePermission(Context context, ResultCollector collector) { - boolean grantsPermission = context.checkCallingOrSelfPermission(FAKE_SIGNATURE_PERMISSION) == PackageManager.PERMISSION_GRANTED; - collector.addResult(context.getString(R.string.self_check_name_perm_granted), grantsPermission, - context.getString(R.string.self_check_resolution_perm_granted)); + boolean grantsPermission = ContextCompat.checkSelfPermission(context, FAKE_SIGNATURE_PERMISSION) == PERMISSION_GRANTED; + collector.addResult(context.getString(R.string.self_check_name_perm_granted), grantsPermission ? Positive : Negative, + context.getString(R.string.self_check_resolution_perm_granted), new CheckResolver() { + @Override + public void tryResolve(Fragment fragment) { + fragment.requestPermissions(new String[]{FAKE_SIGNATURE_PERMISSION}, 0); + } + }); return grantsPermission; } private boolean addSystemSpoofsSignature(Context context, ResultCollector collector) { - boolean spoofsSignature = Constants.GMS_PACKAGE_SIGNATURE_SHA1.equals(PackageUtils.firstSignatureDigest(context, Constants.GMS_PACKAGE_NAME)); - collector.addResult(context.getString(R.string.self_check_name_system_spoofs), spoofsSignature, + boolean spoofsSignature = GMS_PACKAGE_SIGNATURE_SHA1.equals(PackageUtils.firstSignatureDigest(context, Constants.GMS_PACKAGE_NAME)); + collector.addResult(context.getString(R.string.self_check_name_system_spoofs), spoofsSignature ? Positive : Negative, context.getString(R.string.self_check_resolution_system_spoofs)); return spoofsSignature; } diff --git a/play-services-core/src/main/res/drawable-hdpi/ic_magnify.png b/play-services-core/src/main/res/drawable-hdpi/ic_magnify.png new file mode 100644 index 00000000..861b40db Binary files /dev/null and b/play-services-core/src/main/res/drawable-hdpi/ic_magnify.png differ diff --git a/play-services-core/src/main/res/drawable-hdpi/ic_map_marker.png b/play-services-core/src/main/res/drawable-hdpi/ic_map_marker.png new file mode 100644 index 00000000..58c9a14b Binary files /dev/null and b/play-services-core/src/main/res/drawable-hdpi/ic_map_marker.png differ diff --git a/play-services-core/src/main/res/drawable-mdpi/ic_magnify.png b/play-services-core/src/main/res/drawable-mdpi/ic_magnify.png new file mode 100644 index 00000000..fedd0c62 Binary files /dev/null and b/play-services-core/src/main/res/drawable-mdpi/ic_magnify.png differ diff --git a/play-services-core/src/main/res/drawable-mdpi/ic_map_marker.png b/play-services-core/src/main/res/drawable-mdpi/ic_map_marker.png new file mode 100644 index 00000000..f66ef501 Binary files /dev/null and b/play-services-core/src/main/res/drawable-mdpi/ic_map_marker.png differ diff --git a/play-services-core/src/main/res/drawable-xhdpi/ic_magnify.png b/play-services-core/src/main/res/drawable-xhdpi/ic_magnify.png new file mode 100644 index 00000000..5713a86f Binary files /dev/null and b/play-services-core/src/main/res/drawable-xhdpi/ic_magnify.png differ diff --git a/play-services-core/src/main/res/drawable-xhdpi/ic_map_marker.png b/play-services-core/src/main/res/drawable-xhdpi/ic_map_marker.png new file mode 100644 index 00000000..00d32aa4 Binary files /dev/null and b/play-services-core/src/main/res/drawable-xhdpi/ic_map_marker.png differ diff --git a/play-services-core/src/main/res/drawable-xxhdpi/ic_magnify.png b/play-services-core/src/main/res/drawable-xxhdpi/ic_magnify.png new file mode 100644 index 00000000..d9f75bc7 Binary files /dev/null and b/play-services-core/src/main/res/drawable-xxhdpi/ic_magnify.png differ diff --git a/play-services-core/src/main/res/drawable-xxhdpi/ic_map_marker.png b/play-services-core/src/main/res/drawable-xxhdpi/ic_map_marker.png new file mode 100644 index 00000000..78a7dbe2 Binary files /dev/null and b/play-services-core/src/main/res/drawable-xxhdpi/ic_map_marker.png differ diff --git a/play-services-core/src/main/res/drawable-xxxhdpi/ic_magnify.png b/play-services-core/src/main/res/drawable-xxxhdpi/ic_magnify.png new file mode 100644 index 00000000..28456073 Binary files /dev/null and b/play-services-core/src/main/res/drawable-xxxhdpi/ic_magnify.png differ diff --git a/play-services-core/src/main/res/drawable-xxxhdpi/ic_map_marker.png b/play-services-core/src/main/res/drawable-xxxhdpi/ic_map_marker.png new file mode 100644 index 00000000..66945c5a Binary files /dev/null and b/play-services-core/src/main/res/drawable-xxxhdpi/ic_map_marker.png differ diff --git a/play-services-core/src/main/res/layout/pick_place.xml b/play-services-core/src/main/res/layout/pick_place.xml index 0b1f98d2..4a0169aa 100644 --- a/play-services-core/src/main/res/layout/pick_place.xml +++ b/play-services-core/src/main/res/layout/pick_place.xml @@ -22,11 +22,112 @@ - + android:layout_height="0dip" + android:layout_weight="1"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/play-services-core/src/main/res/menu/pick_place.xml b/play-services-core/src/main/res/menu/pick_place.xml new file mode 100644 index 00000000..f05d6d91 --- /dev/null +++ b/play-services-core/src/main/res/menu/pick_place.xml @@ -0,0 +1,26 @@ + + + + + + \ No newline at end of file diff --git a/play-services-core/src/main/res/values-sr/strings.xml b/play-services-core/src/main/res/values-sr/strings.xml index 7ceee953..08386ed9 100644 --- a/play-services-core/src/main/res/values-sr/strings.xml +++ b/play-services-core/src/main/res/values-sr/strings.xml @@ -46,10 +46,6 @@ Поуздај се у Гугл за дозволе апликација Ако је искључено корисник ће бити упитан пре него се захтев за овлашћењем апликација пошаље Гуглу. Неке апликације неће моћи да користе Гуглов налог ако је ово искључено. - Поставка - - микроГ самопровера - Провера исправности подешавања система за коришћење микроГ услуга. Систем има подршку заваравања потписа: Ваш РОМ нема уграђену подршку за заваравање потписа. Ипак можете да користите Xposed или друге начине заваравања потписа. Погледајте документацију да видите који РОМови подржавају заваравање потписа и како да користите микроГ на РОМовима који не подржавају. Систем одобрава дозволу заваравања потписа: diff --git a/play-services-core/src/main/res/values/bools.xml b/play-services-core/src/main/res/values/bools.xml new file mode 100644 index 00000000..7b2133e9 --- /dev/null +++ b/play-services-core/src/main/res/values/bools.xml @@ -0,0 +1,20 @@ + + + + + true + \ No newline at end of file diff --git a/play-services-core/src/main/res/values/strings.xml b/play-services-core/src/main/res/values/strings.xml index 0e672750..aee67516 100644 --- a/play-services-core/src/main/res/values/strings.xml +++ b/play-services-core/src/main/res/values/strings.xml @@ -49,21 +49,6 @@ This can take a couple of minutes." Trust Google for app permissions When disabled, the user is asked before an apps authorization request is sent to Google. Some applications will fail to use the Google account if this is disabled. - Setup - - microG Self-Check - Check if the system is correctly set up to use microG. - System has signature spoofing support: - You ROM has no native support for signature spoofing. You can still use Xposed or other systems to spoof signature. Please check the documentation on which ROMs do support signature spoofing and how to use microG on ROMs that do not. - System grants signature spoofing permission: - This is a strong indicator that the ROM does support signature spoofing, but requires further action to activate it. Please check the documentation on which steps might be required. - System spoofs signature: - This is a strong indicator that the ROM does support signature spoofing, but requires further action to activate it. Please check the documentation on which steps might be required. - %1$s installed: - Install the application %1$s or a compatible one. Please check the documentation on which applications are compatible. - %1$s has correct signature: - Either the installed %1$s is not compatible, signature spoofing is not enabled for it or your ROM does not properly support signature spoofing. Please check the documentation on which applications and ROMs are compatible. - Background services checkin_enable_service @@ -87,4 +72,41 @@ This can take a couple of minutes." Pick a place Place picker is not yet available. + + About + About microG Services Core + Version information and used libraries + + Signature spoofing support + System has signature spoofing support: + Your ROM has no native support for signature spoofing. You can still use Xposed or other systems to spoof signature. Please check the documentation on which ROMs do support signature spoofing and how to use microG on ROMs that do not. + System grants signature spoofing permission: + This is a strong indicator that the ROM does support signature spoofing, but requires further action to activate it. Please check the documentation on which steps might be required. + System spoofs signature: + Please check the documentation on which steps might be required. + + Installed packages + Play Services (GmsCore) + Play Store (Phonesky) + Services Framework (GSF) + %1$s installed: + Install the application %1$s or a compatible one. Please check the documentation on which applications are compatible. + %1$s has correct signature: + Either the installed %1$s is not compatible or signature spoofing is not active for it. Please check the documentation on which applications and ROMs are compatible. + Extended access to Google services + + Permissions granted + Permission to %1$s: + Touch here to grant permission to %1$s. Not granting the permission can result in misbehaving applications. + location + storage + contacts + phone + + microG Services Core: Lacking permission %1$s + + Select this location + Nearby places + (%1$.7f, %2$.7f) + diff --git a/play-services-core/src/main/res/xml/gms_preferences.xml b/play-services-core/src/main/res/xml/gms_preferences.xml index 081e1789..78887a1c 100644 --- a/play-services-core/src/main/res/xml/gms_preferences.xml +++ b/play-services-core/src/main/res/xml/gms_preferences.xml @@ -17,11 +17,9 @@ - @@ -50,4 +48,10 @@ android:targetPackage="com.google.android.gms"/> + + + diff --git a/settings.gradle b/settings.gradle index 92069596..dd82b93d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,3 +8,5 @@ include ':unifiednlp-compat' include ':play-services-api' include ':play-services-core' + +include ':microg-ui-tools'